This project demonstrates a race condition bug in Next.js (verified on 15 and 16) when using middleware (proxy) that reads the request body along with server actions that expect to receive large payloads.
When a Next.js proxy reads the request body and then passes the request to a server action, there's a race condition because requestData.body.finalize() in next-server.js is not awaited. This causes the request body buffer to be replaced asynchronously, and if the server action tries to read the body before the finalization completes, it may receive an incomplete or empty body.
In /node_modules/next/dist/server/next-server.js (line ~1248):
finally {
if (hasRequestBody) {
requestData.body.finalize(); // ❌ Missing await
}
}The finalize() method is async but not awaited, creating a race condition when:
- Middleware/proxy reads the request body
- The body needs to be cloned/buffered for the next handler
- A server action tries to read the body before finalization completes
Follow these steps to reproduce the bug and verify the fix:
pnpm installpnpm buildThis will:
- Build the Next.js app in standalone mode
- Copy static assets
- Inject a random delay into
body-streams.jsto emulate network overhead.
pnpm startThe server will start at http://localhost:3000
- Open http://localhost:3000 in your browser
- The page displays the payload size in bytes (should be ~50KB)
- Click the "Send Large Payload" button
- Expected Result (with bug): Error message or failure due to the race condition
- You should a
SyntaxError: Unexpected end of JSON inputin your terminal.
- You should a
# Press Ctrl+C or Cmd+C to stop the serverpnpm bugfixThis will add await before requestData.body.finalize(); in next-server.js
pnpm start- Open http://localhost:3000 again
- Click the "Send Large Payload" button
- Expected Result (with fix): Success!
- You should see:
✓ Successfully processed [number] bytes of data - Both the proxy and the server action successfully process the body
- No race condition
- You should see:
- Node.js 20 or 22+ (for
--experimental-strip-typesflag) - pnpm
- The random delay in
patch-body-streams.mtsit used to easily emulate network overheads locally.