vercel / vercel/next.js

next build crashes on Node 24.15+ and 25.7+ under Yarn PnP: require.extensions undefined in next-config-ts/require-hook.js

Open Beginner friendly
#92,935 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Module Resolution
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Link to the code that reproduces this issue

https://github.com/kabo/node-24.15-require-extensions-repro

To Reproduce
  1. yarn create next-app@16.2.4 repro (any Next 16 project).
  2. yarn set version 4.14.1
  3. Ensure .yarnrc.yml has default nodeLinker (pnp) — i.e. don't set nodeLinker: node-modules.
  4. Run with Node 24.15.0: yarn build.
  5. Observes the stack trace below.
Current vs. Expected behavior

Expected: next build compiles and produces the .next/ output.

Actual: build exits with

file:///opt/atlassian/pipelines/agent/build/.yarn/__virtual__/next-virtual-51f158077e/6/root/.yarn/berry/cache/next-npm-16.2.4-a755a7c7e3-10.zip/node_modules/next/dist/build/next-config-ts/require-hook.js:35
const oldJSHook = require.extensions['.js'];
                                    ^
TypeError: Cannot read properties of undefined (reading '.js')
    at Object.<anonymous> (file:///.../next/dist/build/next-config-ts/require-hook.js:35:37)
    at loadCJSModule (node:internal/modules/esm/translators:185:3)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:231:7)
    at ModuleJob.runSync (node:internal/modules/esm/module_job:404:39)
    at require (node:internal/modules/esm/translators:145:9)
    at Object.<anonymous> (file:///.../next/dist/build/next-config-ts/transpile-config.js:15:22)
    at loadCJSModule (node:internal/modules/esm/translators:185:3)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:231:7)
    at ModuleJob.runSync (node:internal/modules/esm/module_job:404:39)
    at require (node:internal/modules/esm/translators:145:9)

Node.js v24.15.0

Crash happens regardless of whether the project uses next.config.ts or next.config.mjs, because transpile-config.js imports require-hook.js eagerly at top level.

Root cause (upstream)

This is a regression in Node.js v24.15.0: the require function passed to CJS modules loaded via the ESM loader no longer has .extensions defined when the module source comes through a custom loader (Yarn PnP's zip loader). Verified with a ~10-line reproducer independent of Next.js. See filed issue: <nodejs/node_issue_link_goes_here>.

Likely introduced by nodejs/node#61769 (ESM loader cycle reduction), which also caused nodejs/node#62012 (EBADF fstat on zip fds in the same subsystem).

Requested fix

Even though this is upstream-caused, Next.js reaches for a deprecated API (require.extensions, DEP0007 since 2014) at module top level. One-line defensive access would un-break every Yarn PnP user on Node 24.15+ today, without waiting on a Node patch release:

--- a/packages/next/src/build/next-config-ts/require-hook.ts
+++ b/packages/next/src/build/next-config-ts/require-hook.ts
-const oldJSHook = require.extensions['.js'];
+const oldJSHook = require.extensions?.['.js'];
@@
-    for (const ext of extensions){
-      const oldHook = require.extensions[ext] ?? oldJSHook;
-      require.extensions[ext] = function(mod, oldFilename) {
+    for (const ext of extensions){
+      const oldHook = require.extensions?.[ext] ?? oldJSHook;
+      if (!require.extensions) break;
+      require.extensions[ext] = function(mod, oldFilename) {

(Other accesses in the same file would need similar guards, or the whole registerHook function should early-return when require.extensions is falsy.)

No behavior change on working Node versions, since require.extensions has always been defined there.

Provide environment information
Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Mon, 30 Mar 2026 19:15:57 +0000
  Available memory (MB): 31932
  Available CPU cores: 20
Binaries:
  Node: 24.14.1
  npm: 11.11.0
  Yarn: 4.14.1
  pnpm: N/A
Relevant Packages:
  next: 16.2.4
  eslint-config-next: N/A
  react: 19.2.5
  react-dom: 19.2.5
  typescript: 6.0.3
Next.js Config:
  output: export
Which area(s) are affected? (Select all that apply)

Module Resolution

Which stage(s) are affected? (Select all that apply)

next build (local)

Additional context
  • Breaks in CI on Bitbucket Pipelines using the node:24-slim image as soon as Bitbucket's cache refreshes to the 24.15.0 layer.
  • Workaround for users: pin node:24.14.1-slim (or any Node < 24.15), or switch off Yarn PnP.
  • Node issue: https://github.com/nodejs/node/issues/62786

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/next/src/build/next-config-ts/require-hook.ts, then inspect its eager import from transpile-config.js. Run the linked Yarn PnP reproducer with Node 24.15+ and verify that next build completes and produces the .next/ output without breaking working Node versions.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, next.js, node.js, typescript
Domain
build-system, tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.