denoland/deno · error
ipc stream closed while reading message
Error message
ipc stream closed while reading message
What it means
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.
Source
Thrown at ext/process/ipc.rs:394
.read_buffer
.fill_from_pipe(&mut self.pipe)
.await
.map_err(IpcAdvancedStreamError::Io)?;
}
if let Some(fd) = self.read_buffer.take_raw_fd() {
debug_assert!(raw_fd.is_none());
if raw_fd.is_none() {
raw_fd = Some(fd);
}
}
let available = self.read_buffer.available_mut();
if available.is_empty() {
if read == 0 {
return Ok(None);
} else if length_buffer.message_len().is_some() {
return Err(IpcAdvancedStreamError::Io(io::Error::new(
io::ErrorKind::UnexpectedEof,
"ipc stream closed while reading message",
)));
} else {
return Err(IpcAdvancedStreamError::Io(io::Error::new(
io::ErrorKind::UnexpectedEof,
"ipc stream closed before message length",
)));
}
}
let msg_len = length_buffer.message_len();
let (done, used) = if let Some(msg_len) = msg_len {
if out_buf.len() >= msg_len {
(true, 0)
} else {
let remaining = msg_len - out_buf.len();
out_buf.reserve(remaining);View on GitHub (pinned to 9ad36f7a2c)
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.
Example fix
// before
child.on('message', onMsg); // no error handling: truncated IPC message crashes the parent
// after
child.on('message', onMsg);
child.on('error', (err) => {
if (err.code === 'UNEXPECTED_EOF' || /ipc stream closed while reading/.test(err.message)) {
restartChild(); // peer died mid-message; treat as crash, not bug
}
});
child.on('exit', (code, signal) => { if (signal) restartChild(); }); Defensive patterns
Strategy: try-catch
Try / catch
child.on("error", (e) => {
if (/ipc stream closed while reading message/.test(e.message)) {
// peer died mid-message: treat as crash, restart and replay state
supervisor.restart(child);
}
}); Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ipc stream closed before message length
- ERR_IPC_ONE_PIPE
- ERR_IPC_SYNC_FORK
- ERR_INVALID_HANDLE_TYPE
- ERR_IPC_DISCONNECTED
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/e66f264e73bb808a.
Report an issue: GitHub.