Path Reconciler Errorfix
Error Fix: Two Silent Bugs in the Path Reconciler Refactor
TLDR: After refactoring ctmAdapter.js to export extractSubpaths instead of extractPaths, one file was missed and one case block was missing braces. Both errors are silent in different ways -- one is a module resolution error that only fires at import time, the other is a JavaScript scoping trap that may or may not throw depending on execution path.
Bug 1: Missed File in Refactor
Symptom
Uncaught SyntaxError: The requested module
'/tools/pdf-processor/src/extraction/vector/ctmAdapter.js'
does not provide an export named 'extractPaths' (at pdfAnalyzer.js:17:10)
The error appears the first time the analyzer runs, in the browser console, with no indication of which file contains the stale import.
Root Cause
ctmAdapter.js was refactored: extractPaths renamed to extractSubpaths, return shape changed from { segments, imageMeta, filledRects } to { subpaths, imageMeta, filledRects }. Three files needed updating: geometryWorker.js, pdfAnalyzer.js, and anything else importing from ctmAdapter.
geometryWorker.js was updated. pdfAnalyzer.js was missed.
The Fix
// pdfAnalyzer.js — before
import { extractPaths } from './ctmAdapter.js';
// ...
const segments = extractPaths(opList, vp, OPS);
// pdfAnalyzer.js — after import { extractSubpaths } from './ctmAdapter.js'; import { reconcile } from './pathReconciler.js'; // ... const { subpaths, filledRects: rawFilledRects } = extractSubpaths(opList, vp, OPS); const { segments } = reconcile(subpaths, rawFilledRects, vp);
pdfAnalyzer.js also needed to import reconcile from the new pathReconciler.js because the analysis pipeline uses segments for geometry counts -- it is not enough to just rename the import.
Guard
When renaming an export, search all files importing from that module before implementing. In this project: grep -r "extractPaths" tools/pdf-processor/src. Module resolution errors only fire at load time, not at the line that uses the value -- so the stacktrace points at the import statement, not the call site.
Bug 2: Lexical Declaration in Unbraced Case Clause
Symptom
Potential silent behavior divergence or syntax error depending on JS engine and strict mode. The specific pattern:
// ctmAdapter.js — before
case OPS.closePath:
bufferSeg(rawPendingX, rawPendingY, subpathStartX, subpathStartY);
rawPendingX = subpathStartX; rawPendingY = subpathStartY;
const [x, y] = toViewport(subpathStartX, subpathStartY); // PROBLEM
pendingX = x; pendingY = y;
currentSubpath.closed = true;
break;
const inside an unbraced case clause shares the lexical scope of the entire switch block. Other cases in the same switch also declare const [x, y] inside braced blocks. This creates a scoping conflict: the braced const [x, y] declarations are block-scoped to their own case bodies, but the unbraced one is switch-scoped and can shadow or collide with them depending on execution order.
Root Cause
The refactor added a const destructuring to an existing case that had been written without braces (acceptable when no variable declarations are needed). The new const made the braces necessary.
The Fix
// ctmAdapter.js — after
case OPS.closePath: {
bufferSeg(rawPendingX, rawPendingY, subpathStartX, subpathStartY);
rawPendingX = subpathStartX; rawPendingY = subpathStartY;
const [cpx, cpy] = toViewport(subpathStartX, subpathStartY);
pendingX = cpx; pendingY = cpy;
currentSubpath.closed = true;
break;
}
Two changes: add braces around the case body, rename [x, y] to [cpx, cpy] to avoid any appearance of shadowing the [x, y] names used in other cases above.
Guard
Any time a const or let is added to a case clause, add braces if they are not already there. ESLint's no-case-declarations rule catches this automatically -- if it is not in the lint config, add it.
Lesson
Both bugs would have been caught by a TypeScript build step. The first would be a type error at compile time (unknown export). The second would be a scoping error. The pdf-processor is a vanilla JS Vite project with no TS checking -- in that context, the only reliable catch is a search-before-rename discipline and consistent bracing of case clauses.