{"record":{"id":"8c5dd8a7b9915bc9","repo":"ekzhang/bore","slug":"unexpected-eof","errorCode":null,"errorMessage":"unexpected EOF","messagePattern":"unexpected EOF","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/client.rs","lineNumber":57,"sourceCode":"        to: &str,\n        port: u16,\n        secret: Option<&str>,\n    ) -> Result<Self> {\n        let mut stream = Delimited::new(connect_with_timeout(to, CONTROL_PORT).await?);\n        let auth = secret.map(Authenticator::new);\n        if let Some(auth) = &auth {\n            auth.client_handshake(&mut stream).await?;\n        }\n\n        stream.send(ClientMessage::Hello(port)).await?;\n        let remote_port = match stream.recv_timeout().await? {\n            Some(ServerMessage::Hello(remote_port)) => remote_port,\n            Some(ServerMessage::Error(message)) => bail!(\"server error: {message}\"),\n            Some(ServerMessage::Challenge(_)) => {\n                bail!(\"server requires authentication, but no client secret was provided\");\n            }\n            Some(_) => bail!(\"unexpected initial non-hello message\"),\n            None => bail!(\"unexpected EOF\"),\n        };\n        info!(remote_port, \"connected to server\");\n        info!(\"listening at {to}:{remote_port}\");\n\n        Ok(Client {\n            conn: Some(stream),\n            to: to.to_string(),\n            local_host: local_host.to_string(),\n            local_port,\n            remote_port,\n            auth,\n        })\n    }\n\n    /// Returns the port publicly available on the remote.\n    pub fn remote_port(&self) -> u16 {\n        self.remote_port\n    }","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/ekzhang/bore/blob/00a735a89917642df62d84336a90d9476fa175b5/src/client.rs#L39-L75","documentation":"In `Client::new`, the stream returned `None` (EOF) while waiting for the server's `Hello` response, so no response ever arrived. The connection was closed by the remote side or an intermediary before the handshake completed.","triggerScenarios":"Server process crashed or restarted mid-handshake; a firewall/NAT/load balancer dropped the connection; server actively closed the TCP connection on accept; timeout path where the underlying stream reached EOF before any frame arrived.","commonSituations":"Server behind a proxy with a very short idle/connect timeout; bore server not actually running but something accepted the TCP connection then closed it; transient network interruption; Docker/Kubernetes service with no healthy backend.","solutions":["Retry the connection; if transient it will succeed.","Check that the bore server process is running and healthy on the target host.","Inspect server logs for crashes and intermediary (proxy/firewall) logs for dropped connections.","Increase proxy/firewall connect timeouts if they are cutting the connection during handshake."],"exampleFix":"// before (retry without checking)\nbore local 3000 --to bore.example.com\n// after (in code: retry with backoff on Err)\nfor attempt in 0..3 {\n    match Client::new(...).await {\n        Ok(c) => break,\n        Err(e) if e.to_string().contains(\"unexpected EOF\") => tokio::time::sleep(delay * attempt).await,\n        Err(e) => return Err(e),\n    }\n}","handlingStrategy":"retry","validationCode":"// Cheap liveness probe before the handshake\nif std::net::TcpStream::connect_timeout(&addr, std::time::Duration::from_secs(5)).is_err() {\n    bail!(\"server unreachable at {addr}\");\n}","typeGuard":null,"tryCatchPattern":"match Client::new(...).await {\n    Err(e) if e.to_string().contains(\"unexpected EOF\") => {\n        tokio::time::sleep(backoff).await;\n        retry_connect() // bounded retries with exponential backoff\n    }\n    other => other,\n}","preventionTips":["Implement bounded retries with exponential backoff around Client::new.","Monitor bore server health (systemd/k8s probes) so dead instances are replaced.","Set generous proxy/firewall timeouts so the handshake isn't cut."],"tags":["network","eof","connection"],"backgroundTag":"connection-refused","analyzedSha":"00a735a89917642df62d84336a90d9476fa175b5","analyzedAt":"2026-09-08T13:27:32.996Z","contentChangedAt":"2026-09-08T13:27:32.996Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}