nextjs - 💡(How to fix) Fix Terminal Logs Loop During Routing on pnpm dev in Next.js 16.0.7 [1 comments, 2 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#86849Fetched 2026-04-08 02:08:55
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
labeled ×2closed ×1commented ×1issue_type_added ×1

Error Message

function Postpone({ reason, route }) { const prerenderStore = TURBOPACK__imported__module$5b$externals$5d2f$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js__$5b$external$5d$$28$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js$2c$cjs$29$["workUnitAsyncStorage"].getStore(); const dynamicTracking = prerenderStore && prerenderStore.type === 'prerender-ppr' ? prerenderStore.dynamicTracking : null; postponeWithTracking(route, reason, dynamicTracking); } function postponeWithTracking(route, expression, dynamicTracking) { assertPostpone(); if (dynamicTracking) { dynamicTracking.dynamicAccesses.push({ // When we aren't debugging, we don't need to create another error for the // stack trace. stack: dynamicTracking.isDebugDynamicAccesses ? new Error().stack : undefined, expression }); } TURBOPACK__imported__module$5b$project$5d2f$node_modules$2f2e$pnpm$2f$next$40$16$2e$0$2e$7_$40$babel$2b$core$40$7$2e$28$2e$5_react$2d$dom$40$19$2e$2$2e$1_react$40$19$2e$2$2e$1_$5f$react$40$19$2e$2$2e$1$2f$node_modules$2f$next$2f$dist$2f$server$2f$route$2d$modules$2f$app$2d$page$2f$vendored$2f$rsc$2f$react$2e$js$5b$app$2d$rsc$5d$$28$ecmascript$29$["default"].unstable_postpone(createPostponeReason(route, expression)); } function createPostponeReason(route, expression) { return Route ${route} needs to bail out of prerendering at this point because it used ${expression}. + React throws this special object to indicate where. It should not be caught by + your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error; } function isDynamicPostpone(err) { if (typeof err === 'object' && err !== null && typeof err.message === 'string') { return isDynamicPostponeReason(err.message); } return false; } function isDynamicPostponeReason(reason) { return reason.includes('needs to bail out of prerendering at this point because it used') && reason.includes('Learn more: https://nextjs.org/docs/messages/ppr-caught-error'); } if (isDynamicPostponeReason(createPostponeReason('%%%', '^^^')) === false) { throw Object.defineProperty(new Error('Invariant: isDynamicPostpone misidentified a postpone reason. This is a bug in Next.js'), "__NEXT_ERROR_CODE", { value: "E296", enumerable: false, configurable: true }); } const NEXT_PRERENDER_INTERRUPTED = 'NEXT_PRERENDER_INTERRUPTED'; function createPrerenderInterruptedError(message) { const error = Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", { value: "E394", enumerable: false, configurable: true }); error.digest = NEXT_PRERENDER_INTERRUPTED; return error; } function isPrerenderInterruptedError(error) { return typeof error === 'object' && error !== null && error.digest === NEXT_PRERENDER_INTERRUPTED && 'name' in error && 'message' in error && error instanceof Error; } function accessedDynamicData(dynamicAccesses) { return dynamicAccesses.length > 0; } function consumeDynamicAccess(serverDynamic, clientDynamic) { // We mutate because we only call this once we are no longer writing // to the dynamicTrackingState and it's more efficient than creating a new // array. serverDynamic.dynamicAccesses.push(...clientDynamic.dynamicAccesses); return serverDynamic.dynamicAccesses; } function formatDynamicAPIAccesses(dynamicAccesses) { return dynamicAccesses.filter((access)=>typeof access.stack === 'string' && access.stack.length > 0).map(({ expression, stack })=>{ stack = stack.split('\n') // Remove the "Error: " prefix from the first line of the stack trace as // well as the first 4 lines of the stack trace which is the distance // from the user code and the new Error().stack call. .slice(4).filter((line)=>{ // Exclude Next.js internals from the stack trace. if (line.includes('node_modules/next/')) { return false; } // Exclude anonymous functions from the stack trace. if (line.includes(' (<anonymous>)')) { return false; } // Exclude Node.js internals from the stack trace. if (line.includes(' (node:')) { return false; } return true; }).join('\n'); return Dynamic API Usage Debug - ${expression}:\n${stack}; }); } function assertPostpone() { if (!hasPostpone) { throw Object.defineProperty(new Error(Invariant: React.unstable_postpone is not defined. This suggests the wrong version of React was loaded. This is a bug in Next.js), "__NEXT_ERROR_CODE", { value: "E224", enumerable: false, configurable: true }); } }

Root Cause

function Postpone({ reason, route }) { const prerenderStore = TURBOPACK__imported__module$5b$externals$5d2f$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js__$5b$external$5d$$28$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js$2c$cjs$29$["workUnitAsyncStorage"].getStore(); const dynamicTracking = prerenderStore && prerenderStore.type === 'prerender-ppr' ? prerenderStore.dynamicTracking : null; postponeWithTracking(route, reason, dynamicTracking); } function postponeWithTracking(route, expression, dynamicTracking) { assertPostpone(); if (dynamicTracking) { dynamicTracking.dynamicAccesses.push({ // When we aren't debugging, we don't need to create another error for the // stack trace. stack: dynamicTracking.isDebugDynamicAccesses ? new Error().stack : undefined, expression }); } TURBOPACK__imported__module$5b$project$5d2f$node_modules$2f2e$pnpm$2f$next$40$16$2e$0$2e$7_$40$babel$2b$core$40$7$2e$28$2e$5_react$2d$dom$40$19$2e$2$2e$1_react$40$19$2e$2$2e$1_$5f$react$40$19$2e$2$2e$1$2f$node_modules$2f$next$2f$dist$2f$server$2f$route$2d$modules$2f$app$2d$page$2f$vendored$2f$rsc$2f$react$2e$js$5b$app$2d$rsc$5d$$28$ecmascript$29$["default"].unstable_postpone(createPostponeReason(route, expression)); } function createPostponeReason(route, expression) { return Route ${route} needs to bail out of prerendering at this point because it used ${expression}. + React throws this special object to indicate where. It should not be caught by + your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error; } function isDynamicPostpone(err) { if (typeof err === 'object' && err !== null && typeof err.message === 'string') { return isDynamicPostponeReason(err.message); } return false; } function isDynamicPostponeReason(reason) { return reason.includes('needs to bail out of prerendering at this point because it used') && reason.includes('Learn more: https://nextjs.org/docs/messages/ppr-caught-error'); } if (isDynamicPostponeReason(createPostponeReason('%%%', '^^^')) === false) { throw Object.defineProperty(new Error('Invariant: isDynamicPostpone misidentified a postpone reason. This is a bug in Next.js'), "__NEXT_ERROR_CODE", { value: "E296", enumerable: false, configurable: true }); } const NEXT_PRERENDER_INTERRUPTED = 'NEXT_PRERENDER_INTERRUPTED'; function createPrerenderInterruptedError(message) { const error = Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", { value: "E394", enumerable: false, configurable: true }); error.digest = NEXT_PRERENDER_INTERRUPTED; return error; } function isPrerenderInterruptedError(error) { return typeof error === 'object' && error !== null && error.digest === NEXT_PRERENDER_INTERRUPTED && 'name' in error && 'message' in error && error instanceof Error; } function accessedDynamicData(dynamicAccesses) { return dynamicAccesses.length > 0; } function consumeDynamicAccess(serverDynamic, clientDynamic) { // We mutate because we only call this once we are no longer writing // to the dynamicTrackingState and it's more efficient than creating a new // array. serverDynamic.dynamicAccesses.push(...clientDynamic.dynamicAccesses); return serverDynamic.dynamicAccesses; } function formatDynamicAPIAccesses(dynamicAccesses) { return dynamicAccesses.filter((access)=>typeof access.stack === 'string' && access.stack.length > 0).map(({ expression, stack })=>{ stack = stack.split('\n') // Remove the "Error: " prefix from the first line of the stack trace as // well as the first 4 lines of the stack trace which is the distance // from the user code and the new Error().stack call. .slice(4).filter((line)=>{ // Exclude Next.js internals from the stack trace. if (line.includes('node_modules/next/')) { return false; } // Exclude anonymous functions from the stack trace. if (line.includes(' (<anonymous>)')) { return false; } // Exclude Node.js internals from the stack trace. if (line.includes(' (node:')) { return false; } return true; }).join('\n'); return Dynamic API Usage Debug - ${expression}:\n${stack}; }); } function assertPostpone() { if (!hasPostpone) { throw Object.defineProperty(new Error(Invariant: React.unstable_postpone is not defined. This suggests the wrong version of React was loaded. This is a bug in Next.js), "__NEXT_ERROR_CODE", { value: "E224", enumerable: false, configurable: true }); } }

Code Example

function Postpone({ reason, route }) {
    const prerenderStore = __TURBOPACK__imported__module__$5b$externals$5d2f$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js__$5b$external$5d$__$28$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js$2c$__cjs$29$__["workUnitAsyncStorage"].getStore();
    const dynamicTracking = prerenderStore && prerenderStore.type === 'prerender-ppr' ? prerenderStore.dynamicTracking : null;
    postponeWithTracking(route, reason, dynamicTracking);
}
function postponeWithTracking(route, expression, dynamicTracking) {
    assertPostpone();
    if (dynamicTracking) {
        dynamicTracking.dynamicAccesses.push({
            // When we aren't debugging, we don't need to create another error for the
            // stack trace.
            stack: dynamicTracking.isDebugDynamicAccesses ? new Error().stack : undefined,
            expression
        });
    }
    __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f2e$pnpm$2f$next$40$16$2e$0$2e$7_$40$babel$2b$core$40$7$2e$28$2e$5_react$2d$dom$40$19$2e$2$2e$1_react$40$19$2e$2$2e$1_$5f$react$40$19$2e$2$2e$1$2f$node_modules$2f$next$2f$dist$2f$server$2f$route$2d$modules$2f$app$2d$page$2f$vendored$2f$rsc$2f$react$2e$js__$5b$app$2d$rsc$5d$__$28$ecmascript$29$__["default"].unstable_postpone(createPostponeReason(route, expression));
}
function createPostponeReason(route, expression) {
    return `Route ${route} needs to bail out of prerendering at this point because it used ${expression}. ` + `React throws this special object to indicate where. It should not be caught by ` + `your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error`;
}
function isDynamicPostpone(err) {
    if (typeof err === 'object' && err !== null && typeof err.message === 'string') {
        return isDynamicPostponeReason(err.message);
    }
    return false;
}
function isDynamicPostponeReason(reason) {
    return reason.includes('needs to bail out of prerendering at this point because it used') && reason.includes('Learn more: https://nextjs.org/docs/messages/ppr-caught-error');
}
if (isDynamicPostponeReason(createPostponeReason('%%%', '^^^')) === false) {
    throw Object.defineProperty(new Error('Invariant: isDynamicPostpone misidentified a postpone reason. This is a bug in Next.js'), "__NEXT_ERROR_CODE", {
        value: "E296",
        enumerable: false,
        configurable: true
    });
}
const NEXT_PRERENDER_INTERRUPTED = 'NEXT_PRERENDER_INTERRUPTED';
function createPrerenderInterruptedError(message) {
    const error = Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
        value: "E394",
        enumerable: false,
        configurable: true
    });
    error.digest = NEXT_PRERENDER_INTERRUPTED;
    return error;
}
function isPrerenderInterruptedError(error) {
    return typeof error === 'object' && error !== null && error.digest === NEXT_PRERENDER_INTERRUPTED && 'name' in error && 'message' in error && error instanceof Error;
}
function accessedDynamicData(dynamicAccesses) {
    return dynamicAccesses.length > 0;
}
function consumeDynamicAccess(serverDynamic, clientDynamic) {
    // We mutate because we only call this once we are no longer writing
    // to the dynamicTrackingState and it's more efficient than creating a new
    // array.
    serverDynamic.dynamicAccesses.push(...clientDynamic.dynamicAccesses);
    return serverDynamic.dynamicAccesses;
}
function formatDynamicAPIAccesses(dynamicAccesses) {
    return dynamicAccesses.filter((access)=>typeof access.stack === 'string' && access.stack.length > 0).map(({ expression, stack })=>{
        stack = stack.split('\n') // Remove the "Error: " prefix from the first line of the stack trace as
        // well as the first 4 lines of the stack trace which is the distance
        // from the user code and the `new Error().stack` call.
        .slice(4).filter((line)=>{
            // Exclude Next.js internals from the stack trace.
            if (line.includes('node_modules/next/')) {
                return false;
            }
            // Exclude anonymous functions from the stack trace.
            if (line.includes(' (<anonymous>)')) {
                return false;
            }
            // Exclude Node.js internals from the stack trace.
            if (line.includes(' (node:')) {
                return false;
            }
            return true;
        }).join('\n');
        return `Dynamic API Usage Debug - ${expression}:\n${stack}`;
    });
}
function assertPostpone() {
    if (!hasPostpone) {
        throw Object.defineProperty(new Error(`Invariant: React.unstable_postpone is not defined. This suggests the wrong version of React was loaded. This is a bug in Next.js`), "__NEXT_ERROR_CODE", {
            value: "E224",
            enumerable: false,
            configurable: true
        });
    }
}

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:47 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8103
  Available memory (MB): 8192
  Available CPU cores: 8
Binaries:
  Node: 22.17.1
  npm: 10.9.2
  Yarn: 1.22.22
  pnpm: 10.20.0
Relevant Packages:
  next: 16.0.7 // Latest available version is detected (16.0.7).
  eslint-config-next: N/A
  react: 19.2.1
  react-dom: 19.2.1
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/vercel/next.js/tree/canary/examples/reproduction-template

To Reproduce

  1. Create a new Next.js app.
  2. Run pnpm dev.
  3. Navigate between pages a few times.
  4. Terminal starts looping internal module output.

Current vs. Expected behavior

Current: Terminal enters a loop printing internal resolver and dynamic/static rendering code:


function Postpone({ reason, route }) {
    const prerenderStore = __TURBOPACK__imported__module__$5b$externals$5d2f$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js__$5b$external$5d$__$28$next$2f$dist$2f$server$2f$app$2d$render$2f$work$2d$unit$2d$async$2d$storage$2e$external$2e$js$2c$__cjs$29$__["workUnitAsyncStorage"].getStore();
    const dynamicTracking = prerenderStore && prerenderStore.type === 'prerender-ppr' ? prerenderStore.dynamicTracking : null;
    postponeWithTracking(route, reason, dynamicTracking);
}
function postponeWithTracking(route, expression, dynamicTracking) {
    assertPostpone();
    if (dynamicTracking) {
        dynamicTracking.dynamicAccesses.push({
            // When we aren't debugging, we don't need to create another error for the
            // stack trace.
            stack: dynamicTracking.isDebugDynamicAccesses ? new Error().stack : undefined,
            expression
        });
    }
    __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f2e$pnpm$2f$next$40$16$2e$0$2e$7_$40$babel$2b$core$40$7$2e$28$2e$5_react$2d$dom$40$19$2e$2$2e$1_react$40$19$2e$2$2e$1_$5f$react$40$19$2e$2$2e$1$2f$node_modules$2f$next$2f$dist$2f$server$2f$route$2d$modules$2f$app$2d$page$2f$vendored$2f$rsc$2f$react$2e$js__$5b$app$2d$rsc$5d$__$28$ecmascript$29$__["default"].unstable_postpone(createPostponeReason(route, expression));
}
function createPostponeReason(route, expression) {
    return `Route ${route} needs to bail out of prerendering at this point because it used ${expression}. ` + `React throws this special object to indicate where. It should not be caught by ` + `your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error`;
}
function isDynamicPostpone(err) {
    if (typeof err === 'object' && err !== null && typeof err.message === 'string') {
        return isDynamicPostponeReason(err.message);
    }
    return false;
}
function isDynamicPostponeReason(reason) {
    return reason.includes('needs to bail out of prerendering at this point because it used') && reason.includes('Learn more: https://nextjs.org/docs/messages/ppr-caught-error');
}
if (isDynamicPostponeReason(createPostponeReason('%%%', '^^^')) === false) {
    throw Object.defineProperty(new Error('Invariant: isDynamicPostpone misidentified a postpone reason. This is a bug in Next.js'), "__NEXT_ERROR_CODE", {
        value: "E296",
        enumerable: false,
        configurable: true
    });
}
const NEXT_PRERENDER_INTERRUPTED = 'NEXT_PRERENDER_INTERRUPTED';
function createPrerenderInterruptedError(message) {
    const error = Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
        value: "E394",
        enumerable: false,
        configurable: true
    });
    error.digest = NEXT_PRERENDER_INTERRUPTED;
    return error;
}
function isPrerenderInterruptedError(error) {
    return typeof error === 'object' && error !== null && error.digest === NEXT_PRERENDER_INTERRUPTED && 'name' in error && 'message' in error && error instanceof Error;
}
function accessedDynamicData(dynamicAccesses) {
    return dynamicAccesses.length > 0;
}
function consumeDynamicAccess(serverDynamic, clientDynamic) {
    // We mutate because we only call this once we are no longer writing
    // to the dynamicTrackingState and it's more efficient than creating a new
    // array.
    serverDynamic.dynamicAccesses.push(...clientDynamic.dynamicAccesses);
    return serverDynamic.dynamicAccesses;
}
function formatDynamicAPIAccesses(dynamicAccesses) {
    return dynamicAccesses.filter((access)=>typeof access.stack === 'string' && access.stack.length > 0).map(({ expression, stack })=>{
        stack = stack.split('\n') // Remove the "Error: " prefix from the first line of the stack trace as
        // well as the first 4 lines of the stack trace which is the distance
        // from the user code and the `new Error().stack` call.
        .slice(4).filter((line)=>{
            // Exclude Next.js internals from the stack trace.
            if (line.includes('node_modules/next/')) {
                return false;
            }
            // Exclude anonymous functions from the stack trace.
            if (line.includes(' (<anonymous>)')) {
                return false;
            }
            // Exclude Node.js internals from the stack trace.
            if (line.includes(' (node:')) {
                return false;
            }
            return true;
        }).join('\n');
        return `Dynamic API Usage Debug - ${expression}:\n${stack}`;
    });
}
function assertPostpone() {
    if (!hasPostpone) {
        throw Object.defineProperty(new Error(`Invariant: React.unstable_postpone is not defined. This suggests the wrong version of React was loaded. This is a bug in Next.js`), "__NEXT_ERROR_CODE", {
            value: "E224",
            enumerable: false,
            configurable: true
        });
    }
}

Expected Clean terminal output without internal implementation logs.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:47 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T8103
  Available memory (MB): 8192
  Available CPU cores: 8
Binaries:
  Node: 22.17.1
  npm: 10.9.2
  Yarn: 1.22.22
  pnpm: 10.20.0
Relevant Packages:
  next: 16.0.7 // Latest available version is detected (16.0.7).
  eslint-config-next: N/A
  react: 19.2.1
  react-dom: 19.2.1
  typescript: 5.9.3
Next.js Config:
  output: N/A

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

Output

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

next dev (local)

Additional context

Issue seems tied to Turbopack’s dynamic rendering detection running repeatedly during navigation.

extent analysis

TL;DR

The issue can be mitigated by disabling Turbopack's dynamic rendering detection or upgrading to a version of Next.js that fixes the looping internal module output.

Guidance

  1. Verify Turbopack version: Check if the issue is specific to the current version of Turbopack used by Next.js.
  2. Disable dynamic rendering detection: Try disabling Turbopack's dynamic rendering detection to see if it resolves the issue.
  3. Check for updates: Look for updates to Next.js or Turbopack that may address the issue.
  4. Test with a minimal reproduction: Use the provided reproduction template to test the issue in isolation and verify if the problem persists.

Example

No specific code changes are suggested at this point, as the issue seems related to the interaction between Next.js and Turbopack. However, you can try setting the experimental.turbopack option to false in your next.config.js file to disable Turbopack:

module.exports = {
  //... other configurations ...
  experimental: {
    turbopack: false,
  },
}

Notes

The issue seems to be related to Turbopack's dynamic rendering detection, which is a new feature in Next.js. Disabling this feature or upgrading to a newer version of Next.js may resolve the issue.

Recommendation

Apply a workaround by disabling Turbopack's dynamic rendering detection, as this is a non-invasive change that can help mitigate the issue until a permanent fix is available.

FAIL-SAFE

If the above steps do not resolve the issue, it may be necessary to wait for an update to Next.js or Turbopack that addresses the problem. In the meantime, disabling Turbopack's dynamic rendering detection can help prevent the looping internal module output.

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