Fail worker builds on unresolved imports instead of shipping "No such module"
Status summary#
Done, pending review (PR #2292). Prod remediated (all 22 parked config-worker
feeds fixed and drained). The build now fails loudly when the bundle contains
an import that cannot resolve, instead of shipping an artifact that dies at
instantiation with a cryptic No such module and parks the config feed.
Verified end-to-end against the real bundler in workerd (new e2e tests).
Incident (2nd "Config worker stalled", 2026-07-23)#
misha-kaletsky-s-organization (and, it turned out, 21 other prod projects)
showed the red "Config worker stalled" warning. Thanks to the previous task
(2026-07-23-config-worker-stalled),
the sheet now showed the recorded error:
No such module "iterate/live-state".
imported from "bundle.js"
Root cause chain#
- Seeded config-repo
worker.ts(old template) importsiterate/live-state. - The project's
package.jsonfloats oniterate: https://pkg.pr.new/iterate/iterate/iterate@main. - iterate#2167 (2026-07-21) moved LiveState to
iterate/sdk/capnweband removed the old entry points, deliberately without compatibility aliases. - On the next rebuild, worker-bundler's esbuild resolver hit the removed
subpath:
resolveExportsthrows, the plugin'scatch {}silently marks the import external, and the build "succeeds" with a warning-free artifact whosebundle.jsstill saysimport ... from "iterate/live-state". - Worker Loader injects nothing beyond the artifact's own modules, so
instantiation fails with
No such module; every push delivery toprocessEventBatchfails; three skip-verdicts later the subscription parks. Red sidebar until a human intervenes.
Prod remediation (done, 2026-07-23)#
- One-line fix per affected repo (
repo.edit):iterate/live-state→iterate/sdk/capnweb(both symbols exist there), where the repo still had the old import; thensubscription-resumedon/for every parkedproject-workerfeed across all prod projects. - All 22 drained to lag 0. The only remaining park is
parked-proof-26600with recorded error "intentional poison: parked-warning prd proof" — a deliberate UI-proof project, left as is.
The platform fix#
The build boundary must refuse artifacts that cannot instantiate. Design:
- Extend
patches/@cloudflare__worker-bundler@0.2.1.patch: the esbuild virtual-fs plugin's bare-specifieronResolvenow attaches aFailed to resolve '<specifier>' from <importer>: <reason>warning to the external fallback — distinguishing "the installed '' package does not provide this entry" (the incident shape) from "package ' ' is not installed" — and the relative-path fallthrough warns "file does not exist". Scheme'd specifiers ( cloudflare:*,node:*) and dynamic imports stay silent (a guardedawait import()is legitimate). Regenerated viapnpm patch/patch-commit; installer hunks preserved. -
build-backend.ts:unresolvedImportFailuresfails the build (WorkerBuildFailedError) on those warnings — from the patched esbuild lane and the stock transform lane (bundle: false) — and onFile not found:warnings. Bare node builtins (fs,stream/web, …) exempt viaNODE_BUILTIN_BASE_NAMESin reviewable TS. - Clear, actionable failure message: names each unresolved specifier and
importer, says the worker would fail at startup with
No such module, and hints at the fixes (declare the dependency; update the import;node:prefix for builtins). - Tests: build-backend failure/exemption tables (mocked warnings), plus
two new e2e tests in
worker-build.e2e.test.tsrunning the REAL patched bundler in workerd: an unresolved bare import fails the build with the specifier named, and barepath+node:buffer+cloudflare:workerskeep building and running. worker-bundler cannot run under plain node (wasm module import), so the in-memory unit-test idea was replaced by the e2e lane; also re-ran the overlay and itx-workers e2e suites green as template regression cover.
Explicitly out of scope#
- Compatibility aliases for removed
iterateentry points (#2167 chose not to have them; not relitigating here). - Pinning projects'
iteratespec at seed time instead of floating@main— bigger product question (floating keeps projects on the latest platform; pinning trades that for build reproducibility). Worth a separate task. - Rebuild-and-verify sweeps that would proactively rebuild every project on SDK changes.
Implementation log#
- 2026-07-23: diagnosis + prod sweep (see above), via
doppler run --config prd -- pnpm cli itx run ....