The fallback that reported itself as a measurement
TLDR
A document-level calibration module returned a hardcoded prior whenever its measurement failed, through the same channel as a real measurement. The prior was also in the wrong units. One bad number fragmented every paragraph of every document in the browser build, while the test harness looked perfect. The fix was letting the module return null.
The assumption that seemed reasonable
The module pools line-spacing statistics across all pages of a PDF to calibrate layout tolerances. Its error handling looked defensive: too few histogram samples, or an implausible mode, and it returns a fallback derived from a standard prior.
The reasoning is familiar. A caller always gets a usable number. No nulls to check, no branches downstream. It reads like careful engineering, right up until it is the opposite.
What made this land in production anyway: the module was new, wired into the browser worker as document-level calibration, and the node test scripts that validated the extraction corpus were written before it existed. They called the classifier directly and never passed the module in. Every corpus check kept passing because it was exercising the code path without the poison.
When it failed
I loaded a two-column paper in the browser and every line of every paragraph rendered as its own block. "We introduce a new language representa-" as one paragraph, "tion model called BERT, which stands for" as the next.
The node harness, running the same source files, produced correctly joined paragraphs. Same code, different program: the harness never passed the calibration module into the pipeline, and the browser worker did.
Finding that took longer than fixing it. When two builds of the same source disagree, the diff you want is not in the code, it is in the call sites. Lining up the worker's pipeline invocation against the harness's turned up three optional arguments the harness omitted, and only one of them changed numbers.
What was actually wrong
Three layers, each defensible on its own:
// 1. prior in the wrong units: 12 (font points) against
// measurements taken in scale-2 viewport pixels (~24)
docScale.calibrate(12);
// 2. the plausibility guard, built on that wrong-unit prior, // rejected the TRUE mode, so measurement "failed" if (leading < prior 0.3 || leading > prior 5) return fallback;
// 3. the fallback WAS the prior, returned through the same // channel as a real measurement: 12 * 0.45 = 5.4 return fallback;
Downstream, the page-scale consumer trusted the number and derived a paragraph-gap threshold of 21.6px. The document's line pitch was 24px. Every ordinary line break exceeded the threshold, so every line became a paragraph.
There was a fourth bug hiding under the third: the pre-scan read item.fontSize, a field that does not exist on pdf.js text items, so the font statistics that could have caught the unit mismatch were themselves a constant 12.
What got deleted
The return fallback lines in all three calibrators. Measurement failure now returns null:
_calibrateLeading(deltas, prior) {
if (deltas.length < MIN_SAMPLES) return null;
const mode = histogramMode(deltas);
if (mode < prior 0.5 || mode > prior 2.5) return null;
return refineByMedian(deltas, mode);
}
Evidence
The calibration output for the same document, before and after, from the diagnostic script I used to trace it:
before: {"calibrated":true, "leadingPx":5.4, ...} // the prior, in disguise
after: {"calibrated":true, "leadingPx":26, ...} // measured line pitch
With 5.4, the paragraph threshold lands at 21.6px against a 24px line pitch: every line splits. With 26, it lands at 39px: paragraphs join, and the one heading sitting 40px above its body text still separates. The margin on that last case is 1px, which tells you how little room these thresholds have for laundered guesses.
What replaced it
The consumer already had per-page defaults computed from local font statistics. Null from the document-level module means those defaults stay in charge, which is exactly the behavior that had been validated for months before the module was wired in.
The units bug got fixed too: the prior now derives from the modal measured font size, so the guard and the measurement live in the same unit space. But the structural fix is the null. With correct units and a lying fallback, the next unit drift would replay the whole incident.
The lesson
If a module measures something, its return type must distinguish measured from guessed, because a wrong confident number multiplies through every consumer while a null stops at the first one. And the corollary that let this ship: any optional input that changes numeric behavior belongs in the test harness, or the harness is testing a different program than the one users run.