{"record":{"id":"e66f264e73bb808a","repo":"denoland/deno","slug":"ipc-stream-closed-while-reading-message","errorCode":null,"errorMessage":"ipc stream closed while reading message","messagePattern":"ipc stream closed while reading message","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ext/process/ipc.rs","lineNumber":394,"sourceCode":"          .read_buffer\n          .fill_from_pipe(&mut self.pipe)\n          .await\n          .map_err(IpcAdvancedStreamError::Io)?;\n      }\n\n      if let Some(fd) = self.read_buffer.take_raw_fd() {\n        debug_assert!(raw_fd.is_none());\n        if raw_fd.is_none() {\n          raw_fd = Some(fd);\n        }\n      }\n\n      let available = self.read_buffer.available_mut();\n      if available.is_empty() {\n        if read == 0 {\n          return Ok(None);\n        } else if length_buffer.message_len().is_some() {\n          return Err(IpcAdvancedStreamError::Io(io::Error::new(\n            io::ErrorKind::UnexpectedEof,\n            \"ipc stream closed while reading message\",\n          )));\n        } else {\n          return Err(IpcAdvancedStreamError::Io(io::Error::new(\n            io::ErrorKind::UnexpectedEof,\n            \"ipc stream closed before message length\",\n          )));\n        }\n      }\n\n      let msg_len = length_buffer.message_len();\n      let (done, used) = if let Some(msg_len) = msg_len {\n        if out_buf.len() >= msg_len {\n          (true, 0)\n        } else {\n          let remaining = msg_len - out_buf.len();\n          out_buf.reserve(remaining);","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/process/ipc.rs#L376-L412","documentation":"Deno's advanced (v8 serialization) IPC reader for node:child_process/node:cluster channels reads length-prefixed messages. If the pipe returns EOF (read == 0) after the message-length prefix was already parsed (length_buffer.message_len().is_some()) but before the full payload arrived, the partially received message is abandoned with ErrorKind::UnexpectedEof and this message.","triggerScenarios":"The peer process dies or closes the channel mid-message: child killed by a signal while serializing a large object, abrupt process.exit() during send, OOM kill mid-write, or the channel being torn down before a big payload was flushed.","commonSituations":"fork() plus advanced serialization of large payloads; cluster workers crashing under load; children calling process.exit() while a send() is still buffered; memory-pressure kills truncating channel writes.","solutions":["Treat it as a child crash: listen for 'exit' and inspect code/signal; restart the child and replay any state it owned.","Avoid process.exit() in the child while messages may be in flight; let the event loop drain or ack sends before exiting.","Send large payloads in smaller chunks with application-level acks so a truncated stream loses less.","Attach an 'error' handler on the child/worker so the UnexpectedEof is observed and handled, not fatal to the parent."],"exampleFix":"// before\nchild.on('message', onMsg); // no error handling: truncated IPC message crashes the parent\n\n// after\nchild.on('message', onMsg);\nchild.on('error', (err) => {\n  if (err.code === 'UNEXPECTED_EOF' || /ipc stream closed while reading/.test(err.message)) {\n    restartChild(); // peer died mid-message; treat as crash, not bug\n  }\n});\nchild.on('exit', (code, signal) => { if (signal) restartChild(); });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"child.on(\"error\", (e) => {\n  if (/ipc stream closed while reading message/.test(e.message)) {\n    // peer died mid-message: treat as crash, restart and replay state\n    supervisor.restart(child);\n  }\n});","preventionTips":["Chunk large IPC payloads and ack each chunk so truncation loses minutes, not hours.","Never call process.exit() in children while sends may be buffered; wait for send() callbacks.","Always register both 'error' and 'exit' handlers on forked children and cluster workers."],"tags":["ipc","child-process","cluster","serialization","eof","node-compat"],"backgroundTag":"unexpected-eof","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}