docling-project / docling-project/docling

TableFormer drift on long low-entropy tables: duplicate rows, missing rows, and state-column dropouts on 2-page tables (~150 rows)

Open
#3,401 0 comments 0 reactions 0 assignees View on GitHub
bug triage/close-stale
Dominant language
Python
Stars
66.4k
Forks
4.8k
Avg merge
2d 21h
Merged PRs (30d)
84

Description

### Bug
TableFormer produces structurally corrupted output on tables that span 2 pages and contain ~150 rows with mostly low-entropy numeric content (zeros and small integers). The two do_cell_matching modes trade one symptom for another — neither produces correct output.

Failure mode A — do_cell_matching=True
On the continuation page, the leftmost (row label / State) column is silently emitted as empty for every row. The PDF text cells exist; the matcher fails to associate them with predicted grid positions on the continuation page only.

Failure mode B — do_cell_matching=False
The autoregressive seq2seq decoder drifts after roughly 190 cells of output. Symptoms in the affected region:

Duplicate row emissions — same (state, year) emitted 2× or 3×; sometimes identical values, sometimes one correct copy + one hallucinated zeros copy.
Missing rows — entire year-rows absent from the output (e.g. a state's 2025 row missing).
Year scrambling within a state's 3-row block — e.g. 2025 row emitted before that state's 2023 row.
Orphan rows — numeric row emitted with empty state label, often duplicating values from the preceding row.

**Sample output (do_cell_matching=False):**

Indiana 2023 0 0 0 0 0 0 0
Indiana 2024 0 0 0 0 0 0 0
Iowa 2025 0 12 0 0 0 0 12 <-- year out of order
Iowa 2023 0 0 0 0 0 0 0
Iowa 2024 0 0 0 0 0 0 0
Massachusetts 2025 0 2 0 0 0 0 2 <-- year out of order
Massachusetts 2023 0 0 0 0 0 0 0
Massachusetts 2023 0 0 0 0 0 0 0 <-- duplicate same-year same-values
Massachusetts 2025 1 4** 1 0 0 0 4 <-- duplicate same-year different values
Michigan 2023 0 0 0 0 0 0 0
Michigan 2024 0 0 0 0 0 0 0
Michigan 2025 2 0 0 0 0 2 <-- missing first column value
Minnesota 2025 2 1 0 0 0 0 3 <-- year out of order
Minnesota 2024 0 0 0 0 0 0 0 <-- wrong values
Minnesota 2024 0 2 0 0 0 0 2 <-- duplicate same-year correct values
2025 2 1 0 0 0 0 3 <-- orphan: empty state label
Missouri 2023 0 0 0 0 0 0 0
Missouri 2024 0 2 0 0 0 0 2

**Expected output:**

Indiana 2023 0 0 0 0 0 0 0
Indiana 2024 0 0 0 0 0 0 0
Indiana 2025 0 12 0 0 0 0 12
Iowa 2023 0 0 0 0 0 0 0
Iowa 2024 0 0 0 0 0 0 0
Iowa 2025 0 2 0 0 0 0 2
Massachusetts 2023 0 0 0 0 0 0 0
Massachusetts 2024 0 1 0 0 0 0 1
Massachusetts 2025 1 4** 1 0 0 0 4
Michigan 2023 0 0 0 0 0 0 0
Michigan 2024 0 2 0 0 0 0 2
Michigan 2025 2 1 0 0 0 0 3
Minnesota 2023 0 0 0 0 0 0 0
Minnesota 2024 0 2 0 0 0 0 2
Minnesota 2025 2 1 0 0 0 0 3
Missouri 2023 0 0 0 0 0 0 0
Missouri 2024 0 2 0 0 0 0 2
Missouri 2025 2 0 0 0 0 0 2

In the source PDF the State column is a merged cell with rowspan=3 (one State cell per 3 year rows). Total row count for the full table: 50 states × 3 = 150 rows.

Diagnosis. Counted state-name cell emissions from the raw TableFormer output: states 1–18 (alphabetical) emit exactly once each; from state 19 onward emission counts diverge (Massachusetts 2×, Michigan 2×, Minnesota 3×). Drift threshold is around cell #190 in the decoder's autoregressive sequence — consistent with attention losing positional anchor on long, low-entropy content.

15 configuration combinations tested, all reproduce: HERON / HERON_101 / EGRET_MEDIUM / LARGE / XLARGE layout; images_scale 1.0 and 2.0; force_full_page_ocr and force_backend_text on/off; RapidOCR / EasyOCR (lang=en, conf 0.3) / Tesseract (psm=6); DoclingParse v1/v2/v4 and PyPdfium backends; keep_empty_clusters on/off; TableFormerMode FAST and ACCURATE. Layout / OCR / backend choice does not affect the drift.

A synthetic reproducer PDF generator is attached (generate_reproducer.py) — produces a 2-page PDF with 50 fake state names, 3 year rows each, mostly-zero numeric content, and the State column rendered as a merged cell with rowspan=3 (state name centered vertically, lands at the middle/2024 row's y-coordinate). The original PDF is a confidential client document and cannot be shared publicly.

### Steps to reproduce

Run the attached generate_reproducer.py to produce synthetic_long_table.pdf (2 pages, 50 states × 3 year rows, merged State column).
Run the following script:

```
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions, TableFormerMode

opts = PdfPipelineOptions()
opts.do_table_structure = True
opts.table_structure_options.mode = TableFormerMode.ACCURATE
opts.table_structure_options.do_cell_matching = False # also reproduces with True (different symptom)

converter = DocumentConverter(
format_options={InputFormat.PDF: PdfFormatOption(pipeline_options=opts)}
)
result = converter.convert("synthetic_long_table.pdf")

# Print every table row from every page
doc = result.document
for table in doc.tables:
df = table.export_to_dataframe()
print(df.to_string())
print("---")
```
Inspect the printed rows for the affected region (roughly state #19 onward). Observe:

Duplicated (state, year) rows
Missing year rows for some states
Years emitted out of order within a state's 3-row block
Rows with empty State column
Re-run with opts.table_structure_options.do_cell_matching = True to observe the alternate symptom (empty State column on the continuation page).
...

### Docling version
Docling version: 2.84.0
Docling Core version: 2.74.0
Docling IBM Models version: 3.13.0
Docling Parse version: 5.10.0
Python: cpython-311 (3.11.5)
...

### Python version
Python 3.11.5

[synthetic_long_table.pdf](https://github.com/user-attachments/files/27404809/synthetic_long_table.pdf)

...

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.