pin.

Blog

The failure that should worry you about OCR doesn't look like garbled text. It looks like 98% confidence and a missing paragraph.

pin Founding Team9 min readLeer en español

  • OCR
  • AI Tools
  • Engineering

The pipeline finished the page at 98% confidence. Nothing downstream flagged it. The page was also missing a full line of text.

That’s the finding that reframed how we think about OCR failure. We’ve already written about what OCR is and why it matters for a reader who needs the concept explained. This post is the opposite: for the reader who already knows what OCR is and wants to know what actually breaks it, what the current literature supports, and what we got wrong building it — reused claims link back to that post rather than re-argue them.

Where OCR actually fails, and it isn’t where you’d guess

Garbled characters are the failure mode everyone benchmarks for, and it’s the one that’s easiest to catch — a human glancing at gibberish notices immediately. The failure mode that actually costs you is quieter.

We run a first-generation, general-purpose OCR engine on real scans and it gets confidently, silently wrong in ways a clean benchmark never surfaces:

  • A page’s confidence-scoring step discards its own low-confidence lines before the page-level average ever sees them — so a page that actually contains a bad read reports a clean score, because the bad read was already thrown out by the time anyone checked.
  • A scanned PDF sometimes carries a pre-existing OCR text layer — stamped there by whatever scanner or copier produced it — and the lazy thing to do is trust it as ground truth. We did, at full confidence, even when that foreign layer was visibly garbled (“Contestaci6n de la dernanda”).
  • A page-numbering stamp in the margin gets glued onto the adjacent line of prose, turning a citation into contaminated text: “por delito de 0000372 Terrorismo” is a real example of a folio stamp merging into a criminal charge.
  • A rotation classifier flips a genuinely upright line 180° because its own confidence score narrowly clears threshold — and raising the threshold doesn’t fix it, it just trades one false positive for others measured just as high on the very same page.

None of these are garbled text. All four passed a naive confidence check. The lesson underneath all four: a confidence score is only as trustworthy as everything that fed it, and every one of ours had a place where that broke.

The afternoon that mattered more than any benchmark

We’d already benchmarked our pipeline on a hand-labeled ground truth set. The number that actually changed our architecture didn’t come from that benchmark — it came from one afternoon running the engine against two genuinely dirty documents: public, non-confidential court filings, not client data, chosen specifically because they were the kind of material that makes benchmarks look better than production. Typewriter scans, folio stamps, marginal handwriting, skewed pages, redaction boxes. 52 pages.

The pipeline finished all 52 pages, zero crashes. That’s the easy part. The finding that mattered: the safety cascade we’d built specifically to catch bad reads never triggered once, despite four real, distinct failures happening in that same run. Not because the cascade was badly designed — because each failure found a different gap in what the cascade could see.

Fixing each one taught us something more general than the specific bug:

The confidence signal was lying to itself. Our classical OCR call was silently discarding low-confidence lines inside the library call itself, before our own page-level confidence average ever got to see them. The safety net was averaging only the survivors. A one-line fix — stop discarding inside the call, let our own logic decide what to trust — but it’s the kind of bug that teaches you to ask, for any confidence score you didn’t compute yourself: what did this number already throw away before it reached me?

Trusting a “confident” answer that came from somewhere else. The fix here — detecting when a PDF’s embedded text was drawn in invisible render mode (the standard mark of a scanner or copier stamping OCR text over its own image) and re-reading the pixels regardless of what text was already “there” — took two attempts. The theoretically correct API for the job caused an uncatchable low-level crash at scale, so the actual fix parses the raw content stream by hand. The general lesson survives the specific war story: an upstream system’s confidence is not your confidence, even when it’s dressed as plain text instead of a score.

A threshold isn’t a fix for the thing a threshold can’t see. Raising the rotation classifier’s confidence bar didn’t help, because the false positive we found and the false negatives we’d have created sat on either side of the same narrow band. What worked was adding a second, confidence-gated pass that re-examines a borderline call instead of just trusting a single number harder.

What the current literature actually supports

Three claims worth grounding, because “AI reads documents now” is doing a lot of unearned work in most sales conversations.

Transformer-based, end-to-end models genuinely beat the classical OCR pipeline on accuracy — this isn’t marketing, it’s a measured result. Li et al. (TrOCR, AAAI 2023) report that a pre-trained image-transformer-to-text-transformer model outperforms prior state of the art on printed, handwritten, and scene text recognition, replacing the older CNN-for-vision-plus-RNN-for-text-plus-separate-language-model pipeline with one end-to-end model. That result is real and it’s why a vision-language model belongs in a modern OCR architecture at all.

It does not follow that the newer model wins everywhere, and measuring that honestly is the whole job. We ran our own vision-language model (a 3B-parameter model, chosen for being small enough to run without a rack of GPUs) against our classical engine on the same hand-labeled ground truth, on GPU, at full scale. It roughly halves the classical engine’s error rate on handwriting. It loses to the classical engine on printed and mixed text — the same material where the classical engine was already cheap and accurate. The honest finding wasn’t “the new model is better,” it was “the new model is a handwriting specialist, not a replacement” — and that finding only came from measuring on our own material, not from trusting a benchmark leaderboard.

Benchmarks trained on clean, narrow document sources don’t predict real-world performance, and the field knows it. Pfitzmann et al. (DocLayNet, KDD 2022) built an 80,000-page, human-annotated layout dataset spanning finance, science, patents, tenders, manuals, and legal texts specifically because the prior standard datasets (PubLayNet, DocBank) were sourced entirely from clean scientific-article PDFs and “severely lack in layout variability” — models trained on them don’t generalize to the kind of layout diversity a real document pipeline actually meets. This is the same lesson our dirty-scan afternoon taught us at the OCR-error level: a benchmark built from one narrow source measures how well you do on that source, not on what you’ll actually see.

That gap has a measured downstream cost. Zhang et al. (OHRBench, ICCV 2025) evaluated current OCR solutions specifically for how their errors cascade into retrieval-augmented generation, and found that none of the OCR approaches they tested was sufficient on its own to build a high-quality knowledge base for a RAG system — OCR noise measurably degrades the accuracy of everything built on top of it, not just the transcription itself. A 2025 survey of question-answering over visually rich documents covers the state of the art across this space and is worth reading for the honest limitations section alone, not just the capabilities one.

Why we didn’t switch engines when a newer tool looked good on paper

Once you know newer document-understanding tools exist, the obvious move is to benchmark them and swap if one wins. We did the benchmark. We didn’t swap, and the reason is the part that doesn’t make it into most comparison posts.

We ran three newer open-source document-understanding tools through the same evaluation harness as our production engine. One lost across the board with its default configuration — it broke on accented Spanish and returned empty output on some pages, which for a Spanish-first legal product is disqualifying regardless of what its number looks like on English benchmarks. The other two produced genuinely excellent-looking transcriptions in a quick qualitative check — but came with dependency conflicts we couldn’t resolve inside our existing environment, and licensing that included copyleft code and a revenue-ceiling clause on the model weights. A tool that reads beautifully and that you’re not licensed to run in production at scale isn’t a candidate; it’s a research note for when either the license or the dependency conflict changes. We kept both, versioned and rerunnable, for exactly that day.

The lesson: “which tool has the best accuracy” and “which tool can you actually ship” are different questions, and a fair comparison has to answer both before it means anything.

What we’d tell you to actually do

If you’re building or buying something that reads documents at volume, here’s what earned its place in our process the hard way:

Build your evaluation set from your own hardest material, not a public benchmark. A benchmark tells you how a model does on the documents it was built from. DocLayNet exists because the previous generation of datasets didn’t do this and it showed. Hand-label a ground truth from the ugliest real documents you have — skewed, stamped, handwritten margins, foreign OCR layers already baked in — because that’s the material that will actually reach production, and it’s exactly the material clean benchmarks systematically underrepresent.

Measure past the character level. Character error rate is necessary and not sufficient. OHRBench’s finding — that OCR noise degrades a downstream system’s answers, not just its transcript — means the number you actually care about is task-level: does the field extraction, the citation lookup, the date parsing survive the OCR step, not just does the text look mostly right.

Interrogate every confidence score before you route on it, including the ones you didn’t compute yourself, including the ones baked into a file you’re trusting as already-read. Ask what got discarded before the number reached you.

A bigger model isn’t automatically the fix, and knowing where it actually helps versus where it quietly loses to something cheaper is a measurement you have to run, not an assumption you get to make. Ours helps specifically on handwriting and specifically loses on print — a fact we only know because we measured it on our own material at full scale, not because a paper told us so in general.

We got four real bugs from one afternoon of throwing dirty documents at a system we’d already benchmarked clean. The benchmark told us we were accurate. The dirty documents told us where we were wrong. Both numbers were true; only one of them was useful.

Early access

Entry is still by invitation.

pin runs on a cloud dedicated to your firm, or inside it. Never on a shared one. That is why we open in batches: every setup is accompanied.

  • Installed wherever your firm decides
  • Terms for the first firms