herdrdev/herdr · error · ClientError::ConnectionLost

server closed connection

Error message

server closed connection

What it means

The client's From<protocol::FramingError> impl maps FramingError::UnexpectedEof to ClientError::ConnectionLost with UnexpectedEof and the message 'server closed connection' (src/client/mod.rs:337). UnexpectedEof means the framed stream ended mid-read — the TCP/local socket was closed by the peer before a complete message frame arrived.

Source

Thrown at src/client/mod.rs:337

        }
    }
}

impl std::error::Error for ClientError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            ClientError::ConnectionFailed(err) => Some(err),
            ClientError::ConnectionLost(err) => Some(err),
            ClientError::Protocol(err) => Some(err),
            _ => None,
        }
    }
}

impl From<protocol::FramingError> for ClientError {
    fn from(err: protocol::FramingError) -> Self {
        match err {
            protocol::FramingError::UnexpectedEof => ClientError::ConnectionLost(io::Error::new(
                io::ErrorKind::UnexpectedEof,
                "server closed connection",
            )),
            protocol::FramingError::Io(err) => ClientError::ConnectionLost(err),
            err => ClientError::Protocol(err),
        }
    }
}

// ---------------------------------------------------------------------------
// Terminal setup / restore
// ---------------------------------------------------------------------------

/// Sets up the terminal for client mode (raw mode, optional mouse, keyboard enhancements).
///
/// Returns a guard that restores the terminal when dropped.
fn setup_terminal(mouse_capture: bool) -> io::Result<TerminalGuard> {
    setup_terminal_with_capabilities(true, mouse_capture)

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Check that the herdr server is running: herdr status or herdr server list; restart with herdr daemon start / herdr server start
  2. Inspect server logs for a crash or panic at the moment of disconnect
  3. Clear stale sockets if the server died without cleanup, then reconnect
  4. If it recurs, report the server-side panic backtrace from the logs
Defensive patterns

Strategy: retry

Validate before calling

// verify the server is reachable before connecting
herdr status || herdr daemon start

Type guard

fn is_connection_lost(e: &ClientError) -> bool {
    matches!(e, ClientError::ConnectionLost(err) if err.kind() == io::ErrorKind::UnexpectedEof)
}

Try / catch

match client.run() {
    Err(e) if is_connection_lost(&e) => reconnect_with_backoff(),
    r => r,
}

Prevention

When it happens

Trigger: Any client read path decoding a protocol frame hits EOF because the herdr server process exited, crashed, or closed the socket while the client was reading (handshake, event loop, or attach stream).

Common situations: Server killed or OOM-killed mid-session, herdr update restarting the server, server panic, or a socket path pointing at a dead server's stale socket being cleaned up.

Related errors


AI-assisted analysis of herdrdev/herdr@f457cff4f2 (2026-08-28). Data as JSON: /api/errors/8743a307bc8f41ea. Report an issue: GitHub.