Skip to content

Report unavailable Node builtins as module errors instead of crashing workerd#14619

Open
momomuchu wants to merge 2 commits into
cloudflare:mainfrom
momomuchu:fix/vitest-pool-workers-unresolvable-node-import
Open

Report unavailable Node builtins as module errors instead of crashing workerd#14619
momomuchu wants to merge 2 commits into
cloudflare:mainfrom
momomuchu:fix/vitest-pool-workers-unresolvable-node-import

Conversation

@momomuchu

@momomuchu momomuchu commented Jul 9, 2026

Copy link
Copy Markdown

Fixes #14590.

What

In @cloudflare/vitest-pool-workers, if a Worker under test statically imports (or requires) a node:* builtin that is not actually available at the Worker's resolved compatibility date and flags, workerd crashes with *** Received signal #11: Segmentation fault at pool startup, before any test runs, reporting only Worker exited unexpectedly with no mention of the offending module. The same Worker under wrangler dev fails cleanly with No such module "node:child_process".

Why

The module fallback service maps any id in workerdBuiltinModules to a /node:* redirect. That set is generated at the latest compatibility date, so it includes builtins the running workerd does not serve at the Worker's resolved (earlier) date, or without the required enable_nodejs_* flag. Redirecting one of those drives workerd into a path that segfaults, whereas reporting the module as not found lets workerd resolve at the root and produce a clean No such module error. The redirect was also kept unconditionally for require(), so that path crashed even after the import path was guarded.

How

Compute, per resolved (compatibilityDate, compatibilityFlags), whether each compatibility-gated Node builtin is actually available, applied to both the import and require fallback paths. Availability uses the (enableFlag, disableFlag, defaultOnDate) rules from @cloudflare/unenv-preset (packages/unenv-preset/src/preset.ts): a builtin is available when its disable flag is absent and either its enable flag is present or the resolved date is on or after its default-on date.

Only native-only gated builtins are gated (those whose preset override has no polyfill, hybrid, or injected fallback, so a redirect would crash): os, http2, punycode, cluster, trace_events, domain, wasi, inspector (and inspector/promises), sqlite, dgram, _stream_wrap, repl, child_process, worker_threads, readline (and readline/promises), and _http_server (behind the separate http-server sub-gate at 2025-09-01). Builtins that have a polyfill or are injected or force-enabled by the pool (console, vm, process, perf_hooks, http, https, fs, tty, v8) stay available and resolve unchanged.

To keep the gated table from silently drifting out of sync with preset.ts, a drift-guard test (test/builtin-module-availability.test.ts) pins every entry to the live getCloudflarePreset(...) at its boundary dates and asserts, both ways, that the map covers exactly the native-only gated set. A future preset change to a flag name or date fails CI instead of quietly reintroducing the crash.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: this fixes internal vitest-pool-workers module-resolution behavior (a crash becomes a clear error). There is no user-facing API or documented-behavior change.

@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 94e4154

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cloudflare/vitest-pool-workers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@workers-devprod workers-devprod requested review from a team and penalosa and removed request for a team July 9, 2026 00:09
@workers-devprod

workers-devprod commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/clean-node-import-error.md: [@cloudflare/wrangler]
  • packages/vitest-pool-workers/package.json: [@cloudflare/wrangler]
  • packages/vitest-pool-workers/src/pool/builtin-module-availability.ts: [@cloudflare/wrangler]
  • packages/vitest-pool-workers/src/pool/index.ts: [@cloudflare/wrangler]
  • packages/vitest-pool-workers/src/pool/module-fallback.ts: [@cloudflare/wrangler]
  • packages/vitest-pool-workers/test/builtin-module-availability.test.ts: [@cloudflare/wrangler]
  • packages/vitest-pool-workers/test/validation.test.ts: [@cloudflare/wrangler]
  • pnpm-lock.yaml: [@cloudflare/wrangler]

devin-ai-integration[bot]

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants