{"record":{"id":"801d34817e6b12f7","repo":"facebook/react","slug":"react-currently-only-supports-piping-to-one-writab-801d34","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-webpack/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-webpack/src/server/ReactFlightDOMServerNode.js#L193-L229","documentation":"renderToPipeableStream (react-server-dom-webpack/server.node) returns a {pipe, abort} object whose output may flow to exactly one writable destination. The first pipe() call sets hasStartedFlowing; any second call throws, because the Fizz server cannot fan a single render out to multiple writables.","triggerScenarios":"Calling stream.pipe(destination) twice — for example a success path and an error/fallback path that both pipe, retry logic that re-pipes after a destination error, or one renderToPipeableStream result shared across two request handlers or sockets.","commonSituations":"Custom Express/Fastify SSR servers caching the render result between requests; error handlers that attempt to pipe a fallback shell after piping already began; middleware trying to tee output into a cache and the response by calling pipe twice.","solutions":["Call renderToPipeableStream once per request and pipe exactly once; enforce with a `let piped = false` guard if control flow is complex","If the output is needed in two places, pass a PassThrough to pipe() and branch from it — never call pipe() again","On destination failure use abort()/onError and start a fresh renderToPipeableStream instead of re-piping"],"exampleFix":"// before\nconst {pipe} = renderToPipeableStream(<App />, opts);\nrouter.get('/a', (req, res) => pipe(res));\nrouter.get('/b', (req, res) => pipe(res)); // second pipe -> throws\n\n// after: one render and one pipe per request\nrouter.get('/:page', (req, res) => {\n  const {pipe} = renderToPipeableStream(<App />, opts);\n  pipe(res);\n});","handlingStrategy":"validation","validationCode":"function pipeOnce(pipe, destination) {\n  if (pipeOnce.called) {\n    throw new Error('This stream was already piped — create a new renderToPipeableStream instead.');\n  }\n  pipeOnce.called = true;\n  pipe(destination);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create one renderToPipeableStream per request and pipe exactly once","If you need the output in two sinks, pass a PassThrough to pipe() and branch from it","On destination errors use abort() and start a fresh render — never re-pipe"],"tags":["ssr","streams","render-to-pipeable-stream","node","fizz"],"backgroundTag":"ssr-stream-double-pipe","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}