[Bug]: The cross-page table chunk contains coordinates of multiple pages, but only the first page gets highlighted after clicking on the front end · Issue #16735 · infiniflow/ragflow · GitHub
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: The cross-page table chunk contains coordinates of multiple pages, but only the first page gets highlighted after clicking on the front end #16735
Elasticsearch 8.11.3, MySQL 8.0.39, deployed via Docker Compose
Actual behavior
When clicking a chunk that contains a cross-page table (with data from both page 85 and page 86), the PDF viewer only highlights the text on the first page (page 85). The second page (page 86) is not highlighted at all.
Expected behavior
No response
Steps to reproduce
Upload a PDF file that contains a table spanning two pages (e.g., the table header is on page 85 and the rest continues on page 86).
Wait for parsing to finish, then go to the chunk list of that document.
Identify the chunk that holds the merged cross-page table (the chunk's page_num_int array contains both 85 and 86, and position_int includes coordinates pointing to page 86).
Click on that chunk.
Observe that only the content on page 85 is highlighted; page 86 shows no highlight despite the chunk clearly containing data from that page.
Reproduced locally and the root cause is on the frontend scroll path: web/src/components/document-preview/pdf-preview.tsx calls ref.current(state[0]) when a chunk is selected, but state is one IHighlight per page (buildChunkHighlights in web/src/utils/document-util.ts produces a separate entry for each entry of position_int). For a cross-page chunk only state[0] gets scrollToHighlight; the second page's highlight is rendered but sits off-screen, which matches the reported "page 86 not highlighted at all" symptom.
Backend data looks correct: rag/nlp/__init__.py::add_positions already stores every (pn, left, right, top, bottom) from the parser, so page_num_int and position_int cover both pages. The fix is to scroll to the first highlight of each distinct page so cross-page positions come into view. I'll open a PR shortly.
Excellent root-cause isolation by @Harsh23Kashyap — and worth naming why this is a verification-coverage defect, not a cosmetic highlighting gap, especially for document-heavy / regulated corpora.
The backend data is already correct: page_num_int and position_int faithfully carry every (pn, left, right, top, bottom) for both pages 85 and 86 — so the chunk's provenance is fully stored. The defect is entirely in the human-verification path: the scroll logic calls ref.current(state[0]), and since buildChunkHighlights emits one IHighlight per page, only the first page's highlight is ever scrolled into view. Page 86's highlight is rendered — it just sits off-screen, unreachable without manually navigating. So the data survives and the highlight exists, but the reviewer can't get their eyes onto the second-page portion. That's an asymmetric failure mode: stored-correctly but verifiable-only-partially.
A few angles from the regulated-corpus side, where a "chunk" is often the citation unit a reviewer signs off on:
1. Cross-page tables are exactly the chunks where one-page verification is most dangerous. In contracts, regulatory filings, and financial exhibits, the tables that span pages are disproportionately the operative ones — fee schedules, penalty tiers, milestone payment tables, rate tables that "continued on next page." These are precisely the numbers disputes turn on, and precisely the numbers where "I verified page 85" gives false comfort because the contested figure lives in the rows that spilled to page 86. A reviewer who clicks the chunk, sees the page-85 highlight, and moves on has performed a verification that looks complete but only covered half the cited region. The defect manufactures a verifiable-but-unverified state.
2. "Highlight exists but off-screen" is the silent-corruption signature at the UI layer. It mirrors the same family that's been surfacing in the ingestion/parsing layer nearby: content survives the pipeline, the metadata is correct, but the surface path to it is incomplete — so a human checking the result gets a green-light where there should be a yellow flag. The chunk is marked "source-verified on page 85" while silently also covering page 86; nothing in the interaction tells the reviewer "this citation reaches a second page you haven't looked at." The fix @Harsh23Kashyap proposed (scroll to the first highlight of each distinct page) closes the immediate gap, but the deeper invariant is: if a chunk covers N pages, the verification interaction must surface all N pages, not just the first.
3. Cheap companion signal. Regardless of the scroll fix, emitting a per-chunk covered_pages / page_coverage: {85: highlighted, 86: pending} indicator on the chunk card turns "this chunk spans pages I may not have inspected" from an inference over coordinates into a visible affordance. For a cross-page chunk, surfacing something like "covers 2 pages — click to view page 86" makes the incomplete-coverage state inspectable rather than emergent from whether the user happened to scroll. Same philosophy as a coverage/completeness signal elsewhere in the pipeline: the dangerous case is the chunk that looks fully verified because one page lit up, when it silently covers more.
The backend already does the hard part correctly (storing multi-page provenance). This issue is about making the verification path honor that completeness rather than truncating it at the first page — so that a human's "I checked the source" is true for the whole chunk, not just the part that happened to render on screen.
Activity
one985 commentedon Jul 8, 2026
The image does not contain a git_commit file, so the exact commit ID is unknown.
Harsh23Kashyap commentedon Jul 8, 2026
Reproduced locally and the root cause is on the frontend scroll path:
web/src/components/document-preview/pdf-preview.tsxcallsref.current(state[0])when a chunk is selected, butstateis oneIHighlightper page (buildChunkHighlightsinweb/src/utils/document-util.tsproduces a separate entry for each entry ofposition_int). For a cross-page chunk onlystate[0]getsscrollToHighlight; the second page's highlight is rendered but sits off-screen, which matches the reported "page 86 not highlighted at all" symptom.Backend data looks correct:
rag/nlp/__init__.py::add_positionsalready stores every(pn, left, right, top, bottom)from the parser, sopage_num_intandposition_intcover both pages. The fix is to scroll to the first highlight of each distinct page so cross-page positions come into view. I'll open a PR shortly.zeweihan commentedon Jul 8, 2026
Excellent root-cause isolation by @Harsh23Kashyap — and worth naming why this is a verification-coverage defect, not a cosmetic highlighting gap, especially for document-heavy / regulated corpora.
The backend data is already correct:
page_num_intandposition_intfaithfully carry every(pn, left, right, top, bottom)for both pages 85 and 86 — so the chunk's provenance is fully stored. The defect is entirely in the human-verification path: the scroll logic callsref.current(state[0]), and sincebuildChunkHighlightsemits oneIHighlightper page, only the first page's highlight is ever scrolled into view. Page 86's highlight is rendered — it just sits off-screen, unreachable without manually navigating. So the data survives and the highlight exists, but the reviewer can't get their eyes onto the second-page portion. That's an asymmetric failure mode: stored-correctly but verifiable-only-partially.A few angles from the regulated-corpus side, where a "chunk" is often the citation unit a reviewer signs off on:
1. Cross-page tables are exactly the chunks where one-page verification is most dangerous. In contracts, regulatory filings, and financial exhibits, the tables that span pages are disproportionately the operative ones — fee schedules, penalty tiers, milestone payment tables, rate tables that "continued on next page." These are precisely the numbers disputes turn on, and precisely the numbers where "I verified page 85" gives false comfort because the contested figure lives in the rows that spilled to page 86. A reviewer who clicks the chunk, sees the page-85 highlight, and moves on has performed a verification that looks complete but only covered half the cited region. The defect manufactures a verifiable-but-unverified state.
2. "Highlight exists but off-screen" is the silent-corruption signature at the UI layer. It mirrors the same family that's been surfacing in the ingestion/parsing layer nearby: content survives the pipeline, the metadata is correct, but the surface path to it is incomplete — so a human checking the result gets a green-light where there should be a yellow flag. The chunk is marked "source-verified on page 85" while silently also covering page 86; nothing in the interaction tells the reviewer "this citation reaches a second page you haven't looked at." The fix @Harsh23Kashyap proposed (scroll to the first highlight of each distinct page) closes the immediate gap, but the deeper invariant is: if a chunk covers N pages, the verification interaction must surface all N pages, not just the first.
3. Cheap companion signal. Regardless of the scroll fix, emitting a per-chunk
covered_pages/page_coverage: {85: highlighted, 86: pending}indicator on the chunk card turns "this chunk spans pages I may not have inspected" from an inference over coordinates into a visible affordance. For a cross-page chunk, surfacing something like "covers 2 pages — click to view page 86" makes the incomplete-coverage state inspectable rather than emergent from whether the user happened to scroll. Same philosophy as a coverage/completeness signal elsewhere in the pipeline: the dangerous case is the chunk that looks fully verified because one page lit up, when it silently covers more.The backend already does the hard part correctly (storing multi-page provenance). This issue is about making the verification path honor that completeness rather than truncating it at the first page — so that a human's "I checked the source" is true for the whole chunk, not just the part that happened to render on screen.