You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
N/A — the failure is reproducible with a 3-line Node snippet plus any app whose RSC payload contains a mid-size chunk (analysis below); happy to provide a full repro app if needed.
next dev (Turbopack) an App Router app whose flight/RSC payload produces a serialized chunk between ~2 KiB and 32 KiB (large page props easily do this — e.g. a client component receiving several hundred DB rows).
Request the page.
The response is truncated mid-stream (curl exit 18 / browser "network error"; sometimes a 500), and the dev server logs:
⨯ TypeError: ArrayBuffer is not detachable and could not be cloned.
at ArrayBuffer.transfer (<anonymous>)
⨯ Error: failed to pipe response
Full stack:
TypeError: ArrayBuffer is not detachable and could not be cloned.
at ArrayBuffer.transfer (<anonymous>)
at readableByteStreamControllerEnqueue (node:internal/webstreams/readablestream:3011:29)
at ReadableByteStreamController.enqueue (node:internal/webstreams/readablestream:1278:5)
at Object.write (next/dist/compiled/next-server/app-page-turbo.runtime.dev.js:53:257955)
at writeToDestination (…app-page-turbo.runtime.dev.js:53:131240)
at writeChunkAndReturn (…app-page-turbo.runtime.dev.js:53:132279)
at flushCompletedChunks (…app-page-turbo.runtime.dev.js:53:224430)
at performWork (…app-page-turbo.runtime.dev.js:53:223323)
Current vs. Expected behavior
Current: dev responses for affected pages are truncated/500 on Node 26. Expected: they stream fully, as on Node ≤ 24.
Root cause analysis
createFakeWritableFromReadableStreamController (in the dev runtime) bridges React's flight writer into a type: "bytes"ReadableStream:
write(chunk){if(typeofchunk==="string")chunk=textEncoder.encode(chunk);controller.enqueue(chunk);// byte streams TRANSFER the chunk's ArrayBufferreturntrue;}
Per spec, byte-stream enqueue() transfers the chunk's backing ArrayBuffer. React's node flight build emits some chunks as Buffers, and pool-backed Buffers are non-detachable in Node. Before Node 26 the pool was 8 KiB, so only sub-4 KiB Buffers were pooled (and chunks that small are copied into React's batching view instead of written raw, masking the problem). Node 26's 64 KiB pool means Buffers up to 32 KiB are pooled — so any raw Buffer chunk between the ~2 KiB view-batching threshold and 32 KiB now throws on enqueue. This makes the failure payload-shape-dependent, which made it look intermittent/user-specific.
Minimal demonstration of the underlying incompatibility (no Next involved):
// Node 26.4.0: throws "ArrayBuffer is not detachable and could not be cloned."// Node 24.12.0: passes (5000 > poolSize/2 = 4096, so the Buffer is unpooled)newReadableStream({type: "bytes",start(c){c.enqueue(Buffer.from("x".repeat(5000)))}});
Note that enqueueing a pooled Buffer on Node ≤ 24 was arguably worse: the transfer succeeds and detaches the shared Buffer pool, corrupting unrelated Buffer.from() calls process-wide (ERR_BUFFER_OUT_OF_BOUNDS). So copying Buffer chunks before enqueue (e.g. controller.enqueue(new Uint8Array(chunk)) when chunk.buffer is pool-backed, or always for Buffer instances) fixes both modes.
Production builds are unaffected (different pipe path). Verified on Next 15.x–16.2.11 (latest stable) — the bridge is the same; downgrading Next does not help, pinning Node to 24 does.
Link to the code that reproduces this issue
N/A — the failure is reproducible with a 3-line Node snippet plus any app whose RSC payload contains a mid-size chunk (analysis below); happy to provide a full repro app if needed.
To Reproduce
Buffer.poolSizefrom 8 KiB to 64 KiB.next dev(Turbopack) an App Router app whose flight/RSC payload produces a serialized chunk between ~2 KiB and 32 KiB (large page props easily do this — e.g. a client component receiving several hundred DB rows).The response is truncated mid-stream (curl exit 18 / browser "network error"; sometimes a 500), and the dev server logs:
Full stack:
Current vs. Expected behavior
Current: dev responses for affected pages are truncated/500 on Node 26. Expected: they stream fully, as on Node ≤ 24.
Root cause analysis
createFakeWritableFromReadableStreamController(in the dev runtime) bridges React's flight writer into atype: "bytes"ReadableStream:Per spec, byte-stream
enqueue()transfers the chunk's backingArrayBuffer. React's node flight build emits some chunks asBuffers, and pool-backedBuffers are non-detachable in Node. Before Node 26 the pool was 8 KiB, so only sub-4 KiBBuffers were pooled (and chunks that small are copied into React's batching view instead of written raw, masking the problem). Node 26's 64 KiB pool meansBuffers up to 32 KiB are pooled — so any rawBufferchunk between the ~2 KiB view-batching threshold and 32 KiB now throws on enqueue. This makes the failure payload-shape-dependent, which made it look intermittent/user-specific.Minimal demonstration of the underlying incompatibility (no Next involved):
Note that enqueueing a pooled Buffer on Node ≤ 24 was arguably worse: the transfer succeeds and detaches the shared Buffer pool, corrupting unrelated
Buffer.from()calls process-wide (ERR_BUFFER_OUT_OF_BOUNDS). So copying Buffer chunks before enqueue (e.g.controller.enqueue(new Uint8Array(chunk))whenchunk.bufferis pool-backed, or always forBufferinstances) fixes both modes.Production builds are unaffected (different pipe path). Verified on Next 15.x–16.2.11 (latest stable) — the bridge is the same; downgrading Next does not help, pinning Node to 24 does.
Provide environment information
Which area(s) are affected?
Turbopack, Runtime
Which stage(s) are affected?
next dev (local)