{"record":{"id":"25c128a2615f5a35","repo":"facebook/react","slug":"react-currently-only-supports-piping-to-one-writab-25c128","errorCode":null,"errorMessage":"React currently only supports piping to one writable stream.","messagePattern":"React currently only supports piping to one writable stream\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-server-dom-unbundled/src/server/ReactFlightDOMServerNode.js","lineNumber":211,"sourceCode":"    options ? options.identifierPrefix : undefined,\n    options ? options.temporaryReferences : undefined,\n    options ? options.startTime : undefined,\n    __DEV__ && options ? options.environmentName : undefined,\n    __DEV__ && options ? options.filterStackFrame : undefined,\n    debugChannelReadable !== undefined,\n  );\n  let hasStartedFlowing = false;\n  startWork(request);\n  if (debugChannelWritable !== undefined) {\n    startFlowingDebug(request, debugChannelWritable);\n  }\n  if (debugChannelReadable !== undefined) {\n    startReadingFromDebugChannelReadable(request, debugChannelReadable);\n  }\n  return {\n    pipe<T: Writable>(destination: T): T {\n      if (hasStartedFlowing) {\n        throw new Error(\n          'React currently only supports piping to one writable stream.',\n        );\n      }\n      hasStartedFlowing = true;\n      startFlowing(request, destination);\n      destination.on('drain', createDrainHandler(destination, request));\n      destination.on(\n        'error',\n        createCancelHandler(\n          request,\n          'The destination stream errored while writing data.',\n        ),\n      );\n      // We don't close until the debug channel closes.\n      if (!__DEV__ || debugChannelReadable === undefined) {\n        destination.on(\n          'close',\n          createCancelHandler(request, 'The destination stream closed early.'),","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-server-dom-unbundled/src/server/ReactFlightDOMServerNode.js#L193-L229","documentation":"The object returned by the Node Flight server's pipeToNodeWritable-style API guards pipe() with a hasStartedFlowing flag: one Flight request writes to exactly one writable destination. Calling pipe() a second time on the same request throws, because the request's buffers, drain handlers, and completion state cannot be shared across two streams.","triggerScenarios":"Calling request.pipe(writable) twice — e.g. a retry loop that re-pipes on error, piping to both the HTTP response and a cache/tee, or two consumers of the same render result each calling pipe().","commonSituations":"Implementing render-to-cache by piping the same request to a cache stream and the client; error-handling that retries pipe after a backpressure or socket error; refactoring where pipe is called in two branches that both run.","solutions":["Render once per destination: call renderToPipeableStream again for each consumer instead of re-piping the same request","For caching, tee the destination stream (stream.PassThrough piped onward) or serialize the result once and reuse it","In retry logic, guard with your own hasPiped flag and create a fresh request rather than re-invoking pipe"],"exampleFix":"// before: same request piped twice\nconst {pipe} = renderToPipeableStream(<App />, {});\npipe(httpResponse);\npipe(cacheStream); // throws\n\n// after: one request per destination\npipe(renderToPipeableStream(<App />, {}), httpResponse);\npipe(renderToPipeableStream(<App />, {}), cacheStream);\n\n// or tee a single destination\nconst tee = new PassThrough();\ntee.pipe(httpResponse); tee.pipe(cacheStream);\nrequest.pipe(tee);","handlingStrategy":"validation","validationCode":"// Wrap pipe() so a second call is your own, clearer error\nfunction pipeOnce(pipeable, destination) {\n  if (pipeable._piped) throw new Error('This Flight request was already piped; render a new request per destination.');\n  pipeable._piped = true;\n  return pipeable.pipe(destination);\n}","typeGuard":null,"tryCatchPattern":"try { pipeable.pipe(dest); } catch (e) {\n  if (e.message.includes('only supports piping to one writable stream')) {\n    // recovery: create a fresh render for this destination, do not retry the same request\n    return pipeOnce(renderToPipeableStream(element, options), dest);\n  }\n  throw e;\n}","preventionTips":["One render per destination; tee the writable if you need multiple sinks","Guard retry/error-recovery code from re-entering pipe","Keep the pipeable object private to a single request scope"],"tags":["react-server-components","node","streaming","flight"],"backgroundTag":"stream-piped-twice","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}