Verified: Node v24.15.0 loads CJS modules through the ESM translator (when the
module is served through a custom loader such as Yarn PnP's zip loader) with a
require object that no longer has .extensions. Node v24.14.1 and earlier
work correctly.
Real-world impact: next build on Next.js 15+ installed via Yarn PnP crashes
in next/dist/build/next-config-ts/require-hook.js:35.
hook.cjs/run.mjs— Variant A, plain filesystem. Does not reproduce.variant-b/— Variant B, Yarn PnP. Reproduces.output-24.14.0.txt,output-24.15.0.txt— Variant A outputs (both succeed).output-variant-b-24.14.0.txt,output-variant-b-24.15.0.txt— Variant B outputs (one succeeds, one crashes).node-issue.md— draft bug report for nodejs/node.next-issue.md— draft bug report for vercel/next.js.
Requires two Node versions available locally. Adjust paths.
# Variant A (does NOT reproduce)
/path/to/node-24.14.0 run.mjs
/path/to/node-24.15.0 run.mjs
# Variant B (reproduces)
cd variant-b
/path/to/node-24.14.0 /path/to/yarn-4.14.1/yarn.js node run.mjs # OK
/path/to/node-24.15.0 /path/to/yarn-4.14.1/yarn.js node run.mjs # CRASH- Plain
await import('./hook.cjs')from a filesystem-relative path works on both Node versions. The regression only manifests when the CJS file's source URL comes through a custom loader (PnP serves them asfile:///.../cache/*.zip/node_modules/*/index.cjs). - In the failing case,
typeof requireis'function'buttypeof require.extensionsis'undefined', whereas on 24.14.1 (and in filesystem-loaded CJS generally)require.extensionsis an object with.js,.json, and.nodehandlers. - Stack trace top frames match what Next.js users see:
loadCJSModule (node:internal/modules/esm/translators:185:3) ModuleWrap.<anonymous> (node:internal/modules/esm/translators:231:7) - Likely introduced by nodejs/node#61769 ("lib: reduce cycles in esm loader and load it in snapshot"), which landed in Node 24.x for the first time in 24.15.0. Related: nodejs/node#62012 (EBADF fstat in the same subsystem, same version).