zed-industries/zed · error

Socket closed before a message was received

Error message

Socket closed before a message was received

What it means

recv_json() is the JSON-line protocol reader for the ETW Unix socket. read_line() returned zero bytes, which is EOF: the peer closed the socket without writing a status message. In the parent this surfaces (wrapped as 'Wait for Started status') when the elevated recording subprocess connects via accept() but then exits or crashes before/at sending StatusMessage::Started; in the child it occurs when the parent disappears.

Source

Thrown at crates/etw_tracing/etw_tracing.rs:667

#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(tag = "type")]
pub enum Command {
    Save,
    Cancel,
}

fn send_json<T: serde::Serialize>(writer: &mut impl Write, value: &T) -> Result<()> {
    let json = serde_json::to_string(value).context("Serialize message")?;
    writeln!(writer, "{json}").context("Write to socket")?;
    writer.flush().context("Flush socket")?;
    Ok(())
}

fn recv_json<T: serde::de::DeserializeOwned>(reader: &mut impl BufRead) -> Result<T> {
    let mut line = String::new();
    reader.read_line(&mut line).context("Read from socket")?;
    if line.is_empty() {
        bail!("Socket closed before a message was received");
    }
    serde_json::from_str(line.trim()).context("Parse message")
}

View on GitHub (pinned to f4178619ac)

Solutions

  1. Check the elevated child's logs/stderr - it died before reporting anything; look for panic messages or DLL/load errors in the Zed log
  2. Re-run the recording once to rule out a transient crash during WPR start
  3. Verify the Zed exe that gets elevated is intact (std::env::current_exe() is what ShellExecuteW relaunches; a corrupted/half-updated binary dies instantly)
  4. Exclude/allow the Zed binary in antivirus/EDR if it is killing the elevated child
  5. If the child is crashing reproducibly in record_etw_trace, report a Zed bug with the panic backtrace
Defensive patterns

Strategy: try-catch

Try / catch

match launch_etw_recording(heap_pid, output_path) {
    Ok(session) => Ok(session),
    Err(err) if err.to_string().contains("Socket closed before a message was received") => {
        // child died silently: check crash logs, offer one retry
        check_elevated_child_logs();
        retry_once()
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: (1) launch_etw_recording(): elevated Zed child connects, then dies (panic, early exit, crash in WPR/COM before send_json(Started)) leaving the parent to read EOF. (2) receive_command() in the elevated child when the parent process is killed while the child waits for Save/Stop commands (there it is downgraded to a timed-out Save).

Common situations: Elevated child crashing during WPR startup (panic before the first send_json), UAC elevation launching an exe that immediately terminates (e.g. broken install, missing DLLs), the child being killed by antivirus/EDR, or the socket file at %TEMP%/zed-etw-<pid>.sock being removed. Distinguish from error 260: here the child said nothing at all.

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/ceebefe88210f22c. Report an issue: GitHub.