{"record":{"id":"2026e3de39a9446e","repo":"denoland/deno","slug":"ipc-stream-closed-before-message-length","errorCode":null,"errorMessage":"ipc stream closed before message length","messagePattern":"ipc stream closed before message length","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ext/process/ipc.rs","lineNumber":399,"sourceCode":"\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);\n          let to_copy = available.len().min(remaining);\n          out_buf.extend_from_slice(&available[..to_copy]);\n          (out_buf.len() == msg_len, to_copy)\n        }\n      } else {","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/process/ipc.rs#L381-L417","documentation":"Same advanced IPC reader as the sibling 'closed while reading message' error, but EOF arrived before even the message-length prefix was complete (length_buffer.message_len().is_none()). The channel closed between the start of a header and its end, so no payload could even be partially assembled; the read fails with UnexpectedEof.","triggerScenarios":"The peer closes or dies while a length prefix (few header bytes) was partially written: child killed between two write() calls, channel closed by the parent during teardown, or a worker exiting between messages leaving a torn header in the pipe.","commonSituations":"Races during shutdown/teardown of forked children; killing children with SIGKILL mid-send; channels closed by timeout logic exactly as a new message starts; test harnesses that terminate children aggressively.","solutions":["Handle the error as 'channel torn down': wait for the child 'exit' event to get the real cause (signal vs clean exit).","Order shutdown deliberately: stop sending, await an ack, then close/kill the child, so headers are never cut mid-write.","Use graceful termination (SIGTERM + grace period) instead of SIGKILL so the child can finish writes.","Register 'error' handlers on the channel/worker to convert the EOF into a supervised restart."],"exampleFix":"// before\nsetTimeout(() => child.kill('SIGKILL'), 100); // can cut a length prefix mid-write\n\n// after\nchild.send({ cmd: 'shutdown' }, () => {}); // let the child ack and exit cleanly\nawait once(child, 'exit');\nchild.on('error', (e) => { if (/ipc stream closed/.test(e.message)) restartChild(); });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"child.on(\"error\", (e) => { if (/ipc stream closed before message length/.test(e.message)) supervisor.restart(child); });","preventionTips":["Shut down in order: stop producers, await ack, then terminate children.","Prefer SIGTERM + grace period over SIGKILL so length headers are never cut mid-write.","Keep message sends atomic (one write per message) where possible."],"tags":["ipc","child-process","cluster","eof","shutdown-race","node-compat"],"backgroundTag":"unexpected-eof","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}