Engineering Journal
Pdf Processor
Pdf Processor

Postmortem: When the PDF Pipeline Needed a Manual Override

2026-06-01

TLDR

Our PDF extraction tool initially relied on five global threshold sliders (row band tolerance, paragraph gap, column gap minimum, stream confidence, confidence filter) to allow users to tweak document parsing. In practice, users spent minutes "slider-hunting", adjusting global settings only to find that fixing one page broke another. We deprecated slider-only correction and implemented a direct canvas spatial region editor, reducing document correction time from minutes to seconds.
Incident AspectInitial Slider-Based UXRefactored Canvas Region Editor
Correction MechanismAdjust 5 global numeric threshold slidersDirect mouse manipulation on canvas
Scope of ModificationDocument-wide (All pages affected)Single target page & region only
User Correction Time3 to 5 minutes of trial-and-error slider hunting5 to 10 seconds (Point, click, resize)

Problem statement: the friction of slider-hunting

Our document processing application provided automatic extraction powered by five configurable threshold sliders.

When an extraction misedited a complex page (e.g., merging a table with body copy), users had to guess which slider to adjust.

Users adjusted sliders, clicked "Re-extract", inspected the canvas, and repeated the process. Often, no single global threshold value satisfied all pages simultaneously, leading to user frustration and support tickets.


Technical failure mode: the global parameter abstraction leak

Global thresholds fail when document errors are local:

  1. Conflicting Demands: Page 2 required a wide column gap threshold (20px), while Page 5 required a narrow threshold (10px).
  2. Structural Misclassification: A text block located adjacent to a table was absorbed into the table due to local proximity. No global numeric slider could fix the local proximity error without breaking valid tables elsewhere.

The fix & architecture: direct spatial manipulation layer

We retained automatic detection as the default first pass, but introduced an interactive canvas spatial editor for local corrections:

// REFACTORED: Interactive Canvas Overlay Handler
export class CanvasRegionEditor {
  constructor(canvasElement, pageNum) {
    this.canvas = canvasElement;
    this.pageNum = pageNum;
    this.selectedRegionId = null;
    this.bindEvents();
  }

bindEvents() { // 1. Direct Selection & Hotkey Reclassification window.addEventListener('keydown', (e) => { if (!this.selectedRegionId) return;

if (e.key === 't' || e.key === 'T') { this.reclassifySelectedRegion('LATTICE_TABLE'); } else if (e.key === 'p' || e.key === 'P') { this.reclassifySelectedRegion('PARAGRAPH'); } else if (e.key === 'Delete' || e.key === 'Backspace') { this.suppressSelectedRegion(); } });

// 2. Eight-Handle Mouse Resize & Drag Translation this.canvas.addEventListener('mousedown', (e) => this.handlePointerDown(e)); this.canvas.addEventListener('mousemove', (e) => this.handlePointerMove(e)); }

reclassifySelectedRegion(newType) { updateLocalPageOverride(this.pageNum, this.selectedRegionId, { type: newType, algorithm: 'user-override' }); triggerFastPageReassembly(this.pageNum); } }

Direct manipulation capabilities

Rule of thumb: Use global thresholds for automated first-pass extraction, and provide direct spatial canvas editing tools for local edge-case corrections.
Read this post in the full Engineering Journal →