nextjs - ✅(Solved) Fix next build crashes on Node 24.15+ and 25.7+ under Yarn PnP: require.extensions undefined in next-config-ts/require-hook.js [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#92935Fetched 2026-04-18 05:51:20
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
issue_type_added ×1labeled ×1renamed ×1

Error Message

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

Root Cause

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.

Fix Action

Fix / Workaround

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:

  • 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

PR fix notes

PR #92967: fix(require-hook): guard require.extensions accesses for Node 24.15+ Yarn PnP

Description (problem / solution / changelog)

What?

Guard all require.extensions accesses in packages/next/src/build/next-config-ts/require-hook.ts with optional chaining / early-return guards.

Why?

Node.js v24.15.0 introduced a regression (nodejs/node#61769) where the require function exposed to CJS modules loaded via the ESM loader no longer carries the .extensions property when the module source comes through a custom loader (e.g. Yarn PnP zip loader).

This causes a crash at module evaluation time — before registerHook is even called — making every Yarn PnP user on Node 24.15+ unable to run next build:

TypeError: Cannot read properties of undefined (reading '.js')
    at Object.<anonymous> (.../next/dist/build/next-config-ts/require-hook.js:35:37)

The 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.

How?

  • Use optional chaining for the module-level require.extensions?.['.js'] access (prevents crash at evaluation time)
  • Add if (!require.extensions) return guards to registerHook and deregisterHook (defensive early-exit when the hook API is unavailable)
  • No behaviour change on Node versions where require.extensions is always defined

Fixes #92935

Changed files

  • packages/next/src/build/next-config-ts/require-hook.ts (modified, +12/-4)

Code Example

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

---

--- 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) {

---

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
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

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

To Reproduce

  1. yarn create [email protected] 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

extent analysis

TL;DR

The most likely fix is to add defensive access to require.extensions in the require-hook.ts file to prevent the TypeError.

Guidance

  • Verify that the issue is caused by the regression in Node.js v24.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING