Skip to content

Dev server RSC streaming crashes on Node 26: "ArrayBuffer is not detachable" (Buffer.poolSize 64KiB vs byte-stream enqueue) #96165

Description

@rcsapien

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

  1. Use Node.js 26.x (tested v26.4.0) — the key change is buffer: increase Buffer.poolSize default to 64 KiB nodejs/node#63597, which raised Buffer.poolSize from 8 KiB to 64 KiB.
  2. 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).
  3. 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 (typeof chunk === "string") chunk = textEncoder.encode(chunk);
  controller.enqueue(chunk);  // byte streams TRANSFER the chunk's ArrayBuffer
  return true;
}

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)
new ReadableStream({ 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.

Provide environment information

Operating System: macOS (Darwin 25.4.0, arm64)
Node: 26.4.0 (Homebrew) — fails; 24.12.0 — works
Next.js: 16.2.11 (also reproduced on 16.2.6)
React: 19.2.0
Config: Turbopack dev, cacheComponents: true

Which area(s) are affected?

Turbopack, Runtime

Which stage(s) are affected?

next dev (local)

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalid linkThe issue was auto-closed due to a missing/invalid reproduction link. A new issue should be opened.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions