{"record":{"id":"09921abdca5153c6","repo":"facebook/react","slug":"417-09921a","errorCode":"417","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-flight-server-fb/src/server/ReactFlightDOMServerNode.js","lineNumber":223,"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":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-flight-server-fb/src/server/ReactFlightDOMServerNode.js#L205-L241","documentation":"Thrown by the react-flight-server-fb (Flight / Server Components) node runtime: the object returned by its render-to-pipeable-stream API keeps a hasStartedFlowing closure flag, and a second pipe(destination) call throws because one Flight request can stream its output to only one writable. The request's flow state and buffered chunks are single-use, so re-piping is not a supported operation.","triggerScenarios":"Calling pipe(destination) twice on the same request object returned by the FB flight server's renderToPipeableStream-style API - for example piping to an HTTP response and then to a second sink (log file, cache), or re-piping to a fresh destination after the first one errored.","commonSituations":"Writing one render's payload to multiple sinks; retry logic that calls pipe() again after a socket error; middleware (compression, logging) that transparently pipes the same stream a second time.","solutions":["Call pipe() exactly once per request; render a new request with renderToPipeableStream(...) for each destination.","If several sinks need the same payload, pipe once into a Node stream.PassThrough and tee the bytes from there.","After a destination error, create a fresh render (abort the old request, re-render) instead of re-piping the same object."],"exampleFix":"// before\nconst {pipe} = renderToPipeableStream(<App />, options);\npipe(res);\npipe(tee); // throws: one writable only\n\n// after\nconst {pipe} = renderToPipeableStream(<App />, options);\nconst passThrough = new stream.PassThrough();\npipe(passThrough);\npassThrough.pipe(res);\npassThrough.pipe(tee);","handlingStrategy":"validation","validationCode":"let piped = false;\nfunction pipeOnce(request, destination) {\n  if (piped) {\n    throw new Error('This stream was already piped; render a new request.');\n  }\n  piped = true;\n  return request.pipe(destination);\n}","typeGuard":null,"tryCatchPattern":"try {\n  request.pipe(destination);\n} catch (e) {\n  if (/one writable stream/.test(e.message)) {\n    const fresh = renderToPipeableStream(<App />, options);\n    fresh.pipe(destination);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Treat the pipeable-stream object as single-use: exactly one pipe() per request.","Tee at the stream level (PassThrough) when several sinks need the same output.","Never re-pipe after a destination error; abort and re-render instead."],"tags":["flight","streaming","ssr","server-components"],"backgroundTag":"stream-piped-twice","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}