Circular imports: compiles fine, then "Cannot read properties of undefined" only in production
Problem
Everything passed locally in dev (tsx, watch mode). The production build — tsc to dist/, run with plain node — crashed at boot:
TypeError: Cannot read properties of undefined (reading 'validate')
at Object.<anonymous> (/app/dist/services/order.js:12:34)Same code. The difference was module system and initialization order, and circular imports were hiding in plain sight.
Root cause
services/order.ts imports validation.ts, and validation.ts imports ORDER_LIMITS back from services/order.ts. In dev, tsx's transpile-on-import tends to mask ordering; in the compiled CommonJS output, order.js requires validation.js at the top, which requires order.js again — and gets the partially initialized module (exports not yet assigned). The property exists at type-check time and is undefined at runtime.
ESM handles this differently (live bindings, hoisted function declarations work, const at module scope does not), which is why the same file structure can work with "module": "NodeNext" and break with CommonJS — and vice versa.
npx madge --circular --extensions ts src/
# ✓ Circular dependency found:
… 1 more line in the fix🔒 the fix — including 4 code blocks — is members-only. $1/mo unlocks everything.