rust-lang/rust · error · io::Error
closed
Error message
closed
What it means
Returned by rust-analyzer's bidirectional proc-macro protocol (run_conversation) when the postcard reader yields no buffer from the proc-macro server's stdout - i.e. the stream hit EOF. It is wrapped in a ServerError whose message is 'proc-macro server closed the stream' and whose io field is ErrorKind::UnexpectedEof with text 'closed'. This signals the proc-macro server process terminated mid-conversation.
Source
Thrown at src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol.rs:48
pub type SubCallback<'a> = &'a dyn Fn(SubRequest) -> Result<SubResponse, ServerError>;
pub fn run_conversation(
writer: &mut dyn Write,
reader: &mut dyn BufRead,
buf: &mut Vec<u8>,
msg: BidirectionalMessage,
callback: SubCallback<'_>,
) -> Result<BidirectionalMessage, ServerError> {
let encoded = postcard::encode(&msg).map_err(wrap_encode)?;
postcard::write(writer, &encoded).map_err(wrap_io("failed to write initial request"))?;
loop {
let maybe_buf = postcard::read(reader, buf).map_err(wrap_io("failed to read message"))?;
let Some(b) = maybe_buf else {
return Err(ServerError {
message: "proc-macro server closed the stream".into(),
io: Some(Arc::new(io::Error::new(io::ErrorKind::UnexpectedEof, "closed"))),
});
};
let msg: BidirectionalMessage = postcard::decode(b).map_err(wrap_decode)?;
match msg {
BidirectionalMessage::Response(response) => {
return Ok(BidirectionalMessage::Response(response));
}
BidirectionalMessage::SubRequest(sr) => {
// TODO: Avoid `AssertUnwindSafe` by making the callback `UnwindSafe` once `SourceDatabase`
// becomes unwind-safe (currently blocked by `parking_lot::RwLock` in the VFS).
let resp = match catch_unwind(AssertUnwindSafe(|| callback(sr))) {
Ok(Ok(resp)) => BidirectionalMessage::SubResponse(resp),
Ok(Err(err)) => BidirectionalMessage::SubResponse(SubResponse::Cancel {
reason: err.to_string(),
}),
Err(_) => BidirectionalMessage::SubResponse(SubResponse::Cancel {View on GitHub (pinned to 7088e4b63a)
Solutions
- Check the proc-macro-srv stderr/logs for the crash cause (panic, OOM, version mismatch).
- Ensure rust-analyzer and proc-macro-srv come from the same toolchain/commit.
- Temporarily disable the offending proc-macro crate to confirm it is the trigger.
- Increase available memory / raise ulimits if proc-macro-srv is being OOM-killed.
Example fix
// no code fix; this is a runtime server crash. Diagnostic step: // 1. Run: rustup run nightly proc-macro-srv // 2. Watch stderr for the panic, then fix the offending proc-macro crate.
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the server is alive before sending.
// if proc_macro_server.try_wait()?.is_some() { return Err("server exited"); } Try / catch
match run_conversation(writer, reader, buf, msg, cb) {
Ok(r) => Ok(r),
Err(ServerError { io: Some(ref i), .. })
if i.kind() == io::ErrorKind::UnexpectedEof => {
// server crashed; log stderr, disable proc macros, degrade
Err("proc-macro server crashed mid-conversation".into())
}
Err(e) => Err(e),
} Prevention
- Keep rust-analyzer and proc-macro-srv on the same toolchain/commit.
- Watch proc-macro-srv stderr for panics during macro expansion.
- Provide a config switch to disable the crashing proc-macro crate.
When it happens
Trigger: rust-analyzer sends a BidirectionalMessage to proc-macro-srv and the server process crashes, is killed, or exits before responding; postcard::read returns None because the reader reached EOF. Common during proc-macro expansion when a macro panics inside the server or the server hits a fatal error.
Common situations: proc-macro-srv built against an incompatible toolchain; a derive/attribute macro panicking; OOM killing proc-macro-srv; mismatched protocol versions between rust-analyzer and proc-macro-srv; antivirus killing the child.
Related errors
- proc-macro server did not respond with data
- proc-macro-srv-cli needs to be compiled with the `in-rust-tr
- File path is invalid: {path}
- rust-analyzer Language Server is not available. Please, ensu
- Failed to execute ${path} --version.
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/281da683490519b6.
Report an issue: GitHub.