Context
split_book.py, get_chapters_from_outline / _walk_outline (outline-based chapter detection).
Problem
When a PDF's outline includes a bookmark that doesn't point at a page in the document — e.g. a bookmark whose action is a URI link (/A << /S /URI /URI (https://...) >>) instead of a /Dest page destination — reader.get_destination_page_number(item) returns None instead of raising. _walk_outline only guards against destination resolution raising; it doesn't check for a None return, so (None, title) is appended to the entries list. The subsequent entries.sort(key=lambda x: x[0]) in get_chapters_from_outline then blows up comparing None to int, crashing the whole run.
Real books frequently mix non-chapter bookmarks into their outline (e.g. "Visit our website", footnote/reference links), so this is a realistic failure, not just theoretical — confirmed with a synthetic PDF.
Reproduction
- Build a PDF whose outline has one normal chapter bookmark (pointing at a page) and one bookmark whose action is a URI link rather than a page destination (via pypdf: add a
DictionaryObject outline child with /A = a URI action dict and no /Dest).
- Run
python split_book.py that.pdf --level 1 --list.
Expected
Either: the non-page bookmark is skipped (like other unresolvable entries already are) and the rest of the plan prints normally, or the tool exits with a clear, specific message — never a raw traceback.
Actual
Traceback (most recent call last):
...
File "split_book.py", line 88, in get_chapters_from_outline
entries.sort(key=lambda x: x[0])
TypeError: '<' not supported between instances of 'NoneType' and 'int'
Acceptance criteria
Context
split_book.py,get_chapters_from_outline/_walk_outline(outline-based chapter detection).Problem
When a PDF's outline includes a bookmark that doesn't point at a page in the document — e.g. a bookmark whose action is a URI link (
/A << /S /URI /URI (https://...) >>) instead of a/Destpage destination —reader.get_destination_page_number(item)returnsNoneinstead of raising._walk_outlineonly guards against destination resolution raising; it doesn't check for aNonereturn, so(None, title)is appended to the entries list. The subsequententries.sort(key=lambda x: x[0])inget_chapters_from_outlinethen blows up comparingNonetoint, crashing the whole run.Real books frequently mix non-chapter bookmarks into their outline (e.g. "Visit our website", footnote/reference links), so this is a realistic failure, not just theoretical — confirmed with a synthetic PDF.
Reproduction
DictionaryObjectoutline child with/A= a URI action dict and no/Dest).python split_book.py that.pdf --level 1 --list.Expected
Either: the non-page bookmark is skipped (like other unresolvable entries already are) and the rest of the plan prints normally, or the tool exits with a clear, specific message — never a raw traceback.
Actual
Acceptance criteria
None(as well as ones that raise) are skipped the same way, with no crash.