{"record":{"id":"2ce6a0571e06a532","repo":"sinelaw/fresh","slug":"server-closed-connection","errorCode":null,"errorMessage":"Server closed connection","messagePattern":"Server closed connection","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/client/mod.rs","lineNumber":79,"sourceCode":"\n/// Run the client with an already-established connection\n///\n/// This is useful when the caller has already established a connection\n/// (e.g., after retrying connection attempts). Performs handshake then relay.\npub fn run_client_with_connection(\n    config: ClientConfig,\n    conn: ClientConnection,\n) -> io::Result<ClientExitReason> {\n    // Perform handshake\n    let hello = ClientHello::new(config.term_size);\n    let hello_json = serde_json::to_string(&ClientControl::Hello(hello))\n        .map_err(|e| io::Error::other(e.to_string()))?;\n    conn.write_control(&hello_json)?;\n\n    // Read server response\n    let response = conn\n        .read_control()?\n        .ok_or_else(|| io::Error::new(io::ErrorKind::UnexpectedEof, \"Server closed connection\"))?;\n\n    let server_msg: ServerControl =\n        serde_json::from_str(&response).map_err(|e| io::Error::other(e.to_string()))?;\n\n    match server_msg {\n        ServerControl::Hello(server_hello) => {\n            if server_hello.protocol_version != PROTOCOL_VERSION {\n                return Ok(ClientExitReason::VersionMismatch {\n                    server_version: server_hello.server_version,\n                });\n            }\n            tracing::info!(\n                \"Connected to session '{}' (server {})\",\n                server_hello.session_id,\n                server_hello.server_version\n            );\n        }\n        ServerControl::VersionMismatch(mismatch) => {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/client/mod.rs#L61-L97","documentation":"run_client_with_connection performs the initial handshake: it writes a hello control message and then reads the server's control reply. If read_control() returns None (the server closed the socket/pipe before sending a response), it raises io::ErrorKind::UnexpectedEof 'Server closed connection'.","triggerScenarios":"Server process crashes or exits immediately after accepting the connection; wrong socket/pipe path (another process listening that disconnects); server rejects/never answers the hello due to protocol or version mismatch; permission/timeout causing the server to drop the connection.","commonSituations":"Fresh-editor server binary not running or dying on startup (bad config, port/pipe conflicts, missing permissions); version mismatch between client and server leading the server to close early; connecting to a stale socket file left from a previous run.","solutions":["Verify the server process is running and the connection path (socket/pipe) is correct","Check server logs/stderr for a startup crash or protocol rejection","Remove stale socket files and restart the server","Confirm client and server versions/protocol are compatible","Retry the connection with backoff in case of transient startup timing"],"exampleFix":"// before\nlet server = spawn_server()?;\nrun_client(&server)?;\n// after\nlet server = spawn_server()?;\nwait_until_ready(&server, Duration::from_secs(5))?; // poll health before handshake\nrun_client(&server)?;","handlingStrategy":"retry","validationCode":"fn server_reachable(path: &Path) -> bool { path.exists() && std::os::unix::net::UnixStream::connect(path).is_ok() }","typeGuard":null,"tryCatchPattern":"let resp = loop {\n    match run_client(&conn) {\n        Err(e) if e.kind() == io::ErrorKind::UnexpectedEof && attempts < 3 => { attempts += 1; sleep(backoff); restart_server()?; }\n        other => break other,\n    }\n};","preventionTips":["Wait for a server readiness signal (health file/pipe) before handshaking","Log server stderr to diagnose crashes at startup","Clean up stale socket files before connecting","Pin client/server protocol versions and check them early"],"tags":["ipc","connection","eof","handshake"],"backgroundTag":"connection-refused","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}