nextjs - ✅(Solved) Fix Race condition with Node.js middleware body cloning [2 pull requests, 6 comments, 5 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#85416Fetched 2026-04-08 02:15:53
View on GitHub
Comments
6
Participants
5
Timeline
33
Reactions
8
Timeline (top)
subscribed ×12commented ×6cross-referenced ×5labeled ×3

Error Message

~/Code/Tests/nextjs-middleware-bug main* ⇡ ❯ pnpm start

[email protected] start /Users/lucas/Code/Tests/nextjs-middleware-bug node .next/standalone/server.js

▲ Next.js 16.0.1-canary.3

✓ Starting... ✓ Ready in 37ms Proxy - body length: 50333 bytes ⨯ SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) { digest: '3042448573' }

Root Cause

This error basically happens because we're not awaiting the body to be fully cloned before invoking the server action, in here: https://github.com/vercel/next.js/blob/1b45163bce3dab30d7a79dff95238b84016b54c2/packages/next/src/server/next-server.ts#L1757.

Fix Action

Fix / Workaround

To reproduce it, you can follow the steps from the previous section, but run pnpm bugfix before pnpm start. That will patch the file with the missing await, fixing the previous error.

PR fix notes

PR #85418: fix(nodejs-middleware): await for body cloning to be properly finalized

Description (problem / solution / changelog)

Fixes https://github.com/vercel/next.js/issues/85416.

This is a follow up to https://github.com/vercel/next.js/pull/77662, where the Node.js middleware was fixed to also support reading (and duplicating) the body's request before being passed to the server action.

However, in that PR, an await was missed while calling the .finalize() method, which returns a Promise. That missing await would sometimes cause a bug, where the server action would be invoked before the body was completely cloned, causing the bug mentioned in the issue above.

Changed files

  • packages/next/src/server/next-server.ts (modified, +1/-1)
  • test/e2e/app-dir/actions/app/body-finalize/actions.js (added, +13/-0)
  • test/e2e/app-dir/actions/app/body-finalize/page.js (added, +27/-0)
  • test/e2e/app-dir/actions/components/DefaultLayout.tsx (added, +14/-0)
  • test/e2e/app-dir/actions/middleware-node.js (modified, +9/-0)
  • test/production/app-dir/actions/app-action-body-finalize-output-standalone.test.ts (added, +87/-0)
  • test/production/app-dir/actions/app/body-finalize/actions.js (added, +13/-0)
  • test/production/app-dir/actions/app/body-finalize/page.js (added, +27/-0)
  • test/production/app-dir/actions/app/layout.js (added, +8/-0)
  • test/production/app-dir/actions/middleware.js (added, +27/-0)
  • test/production/app-dir/actions/next.config.js (added, +11/-0)
  • test/production/next-server-nft/next-server-nft.test.ts (modified, +0/-2)

Code Example

~/Code/Tests/nextjs-middleware-bug main*❯ pnpm start

> nextjs-middleware-bug@0.1.0 start /Users/lucas/Code/Tests/nextjs-middleware-bug
> node .next/standalone/server.js

Next.js 16.0.1-canary.3
   - Local:        http://localhost:3000
   - Network:      http://0.0.0.0:3000

Starting...
Ready in 37ms
Proxy - body length: 50333 bytes
SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>) {
  digest: '3042448573'
}

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:26 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T6041
  Available memory (MB): 24576
  Available CPU cores: 14
Binaries:
  Node: 22.13.0
  npm: 11.2.0
  Yarn: N/A
  pnpm: 10.7.1
Relevant Packages:
  next: 16.0.0 // Latest available version is detected (16.0.0).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: N/A
Next.js Config:
  output: standalone
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/lucasadrianof/nextjs-middleware-bug

To Reproduce

  1. pnpm install from the project folder.
  2. pnpm build. This will build the project and add a random delay to the body cloning process to make the bug happen more consistently.
  3. pnpm start.
  4. Open http://localhost:3000/ in your browser.
  5. Click the Send Large Payload button.
  6. The request will fail. You should see a SyntaxError: Unexpected end of JSON input in your terminal.
~/Code/Tests/nextjs-middleware-bug main* ⇡
❯ pnpm start

> [email protected] start /Users/lucas/Code/Tests/nextjs-middleware-bug
> node .next/standalone/server.js

   ▲ Next.js 16.0.1-canary.3
   - Local:        http://localhost:3000
   - Network:      http://0.0.0.0:3000

 ✓ Starting...
 ✓ Ready in 37ms
Proxy - body length: 50333 bytes
 ⨯ SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>) {
  digest: '3042448573'
}

Current vs. Expected behavior

Current behavior:

<img width="844" height="128" alt="Image" src="https://github.com/user-attachments/assets/2d73fda3-64a1-4615-b5a4-bc6d34577cac" />

Expected behavior:

<img width="322" height="144" alt="Image" src="https://github.com/user-attachments/assets/eb1d4ec4-773f-4eb5-9f67-c5064dda0737" />

The request body cloning should be properly awaited before invoking the server action handler. This is the output I get once I run the script to apply the bugfix:

To reproduce it, you can follow the steps from the previous section, but run pnpm bugfix before pnpm start. That will patch the file with the missing await, fixing the previous error.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:26 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T6041
  Available memory (MB): 24576
  Available CPU cores: 14
Binaries:
  Node: 22.13.0
  npm: 11.2.0
  Yarn: N/A
  pnpm: 10.7.1
Relevant Packages:
  next: 16.0.0 // Latest available version is detected (16.0.0).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: N/A
Next.js Config:
  output: standalone

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

Middleware, Server Actions

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

next start (local)

Additional context

Hello!

We noticed this bug in our production app, where we're running Next.js with the output: standalone option with Docker.

This bug is really hard to be reproduced locally, since it happens in a race condition, when there's some sort of delay between cloning the request body. It also depends on the request body being relatively large. It was specially tricky to reproduce it while trying to debug it, since the await in the debugging would invalidate the race condition 100% of the times.

So to make this consistently reproducible locally, I added a random delay in that specific function.

This error basically happens because we're not awaiting the body to be fully cloned before invoking the server action, in here: https://github.com/vercel/next.js/blob/1b45163bce3dab30d7a79dff95238b84016b54c2/packages/next/src/server/next-server.ts#L1757.

That method returns a Promise, as defined in here: https://github.com/vercel/next.js/blob/1b45163bce3dab30d7a79dff95238b84016b54c2/packages/next/src/server/body-streams.ts#L39.

extent analysis

TL;DR

The most likely fix is to add an await keyword when cloning the request body to ensure it is fully cloned before invoking the server action handler.

Guidance

  • The issue is caused by a race condition where the server action handler is invoked before the request body is fully cloned, resulting in a SyntaxError: Unexpected end of JSON input.
  • To fix this, add an await keyword when cloning the request body, as shown in the bugfix script.
  • Verify the fix by running pnpm bugfix before pnpm start and checking that the request body is properly cloned before invoking the server action handler.
  • To mitigate this issue in production, ensure that the request body is fully cloned before invoking the server action handler, and consider adding error handling to catch any potential errors.

Example

// Before
const clonedBody = cloneRequestBody(req);

// After
const clonedBody = await cloneRequestBody(req);

Notes

  • The issue is specific to Next.js with the output: standalone option and may not apply to other configurations.
  • The fix assumes that the cloneRequestBody function returns a Promise, as defined in the Next.js source code.

Recommendation

Apply workaround: Add an await keyword when cloning the request body to ensure it is fully cloned before invoking the server action handler. This fix is recommended because it directly addresses the root cause of the issue and provides a clear solution.

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