fix(docling): drop off-by-one page-number shift in DoclingBackend - #5
Merged
Merged
Conversation
…dexed
DoclingBackend.`_page_1_indexed_from_item` was treating
`ProvenanceItem.page_no` as 0-indexed and adding +1 on top. In docling
2.92 the field is already 1-indexed (it is used as-is to index
`DoclingDocument.pages`, e.g. `doc.pages[prov.page_no]` and
`doc.pages[1]` for a single-page document).
Effect of the bug: every `Block.page` value emitted by the docling
backend was off by one. A block on the first page reported `page=2`,
the last page reported one past the end, etc. Downstream consumers
(RAG citations, page-anchored UIs, search snippets, the `bigos parse`
JSON output) were therefore pointing users to the wrong page. The
existing per-block tests only asserted block-kind counts, not page
numbers, so the regression slipped through review with the initial
docling integration.
Reproducer (1-page PDF):
doc = await DoclingBackend().run(src)
{b.page for b in doc.blocks if b.page is not None} # was {2}, now {1}
Fix: pass the docling page number through unchanged after coercion,
treat `< 1` as unknown, and document the convention so future edits
do not re-introduce the shift.
Tests: a focused unit test covers the helper for the in-range,
out-of-range, missing-prov and bad-value paths; a slow end-to-end test
runs the docling backend against the existing single-page fixture and
asserts every block reports `page == 1`.
Co-authored-by: Bartłomiej Rosa <bartrosa@users.noreply.github.com>
bartrosa
marked this pull request as ready for review
May 23, 2026 12:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug and impact
DoclingBackendproduced wrong page numbers for every block in every parsed document. A block on page 1 reportedpage=2, the last page reported one past the end of the document, etc.Downstream effects across the project's stated use cases:
bigos parse --format=json— the JSON output that ingestion pipelines persist contains incorrectpagefields.Document.blockshighlight the wrong region.This is silent data corruption: nothing crashes, no error is logged — every block just lies about its provenance.
Root cause
In
src/bigos/backends/docling.py,_page_1_indexed_from_item(...)returnedn + 1, on the assumption that docling'sProvenanceItem.page_nowas 0-indexed.In docling 2.92 (and the installed
docling-core2.74)prov.page_nois already 1-indexed: it is used as-is to indexDoclingDocument.pages(e.g.doc.pages[prov.page_no]), and a single-page document'spagesdict is keyed{1: ...}. Adding+1on top therefore shifts every block.Reproducer (single-page PDF fixture in
tests/fixtures/simple_text.pdf):The existing tests only asserted block-kind counts, not page numbers, so the bug slipped through the initial docling integration review.
Fix and validation
int(...)coercion. Treat< 1(and missing/bad values) as unknown.Validation:
test_page_helper_passes_through_1_indexedcovers the in-range, missing-prov, and bad-value branches without requiring docling at runtime.test_parse_simple_text_page_number_is_oneruns the docling backend on the existing single-page fixture and asserts every block reportspage == 1.uv run pytest) — 67 passed, no regressions.The fix is minimal (1 file, ~10 lines) and does not touch any other behavior.