{"record":{"id":"e17c1f0affd392ae","repo":"affaan-m/ECC","slug":"unexpected-eof-while-reading-http-request","errorCode":null,"errorMessage":"Unexpected EOF while reading HTTP request","messagePattern":"Unexpected EOF while reading HTTP request","errorType":"http","errorClass":"anyhow::Error","httpStatus":400,"severity":"warning","filePath":"ecc2/src/main.rs","lineNumber":4198,"sourceCode":"        }\n        _ => write_http_response(\n            stream,\n            404,\n            \"application/json\",\n            &serde_json::json!({\"error\": \"not found\"}).to_string(),\n        ),\n    }\n}\n\nfn read_http_request(\n    stream: &mut TcpStream,\n) -> Result<(String, String, BTreeMap<String, String>, Vec<u8>)> {\n    let mut buffer = Vec::new();\n    let mut temp = [0_u8; 1024];\n    let header_end = loop {\n        let read = stream.read(&mut temp)?;\n        if read == 0 {\n            anyhow::bail!(\"Unexpected EOF while reading HTTP request\");\n        }\n        buffer.extend_from_slice(&temp[..read]);\n        if let Some(index) = buffer.windows(4).position(|window| window == b\"\\r\\n\\r\\n\") {\n            break index + 4;\n        }\n        if buffer.len() > 64 * 1024 {\n            anyhow::bail!(\"HTTP request headers too large\");\n        }\n    };\n\n    let header_text = String::from_utf8(buffer[..header_end].to_vec())\n        .context(\"HTTP request headers were not valid UTF-8\")?;\n    let mut lines = header_text.split(\"\\r\\n\");\n    let request_line = lines\n        .next()\n        .filter(|line| !line.trim().is_empty())\n        .ok_or_else(|| anyhow::anyhow!(\"Missing HTTP request line\"))?;\n    let mut request_parts = request_line.split_whitespace();","sourceCodeStart":4180,"sourceCodeEnd":4216,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/main.rs#L4180-L4216","documentation":"The built-in HTTP server's request reader loops reading from the client socket until it finds the `\\r\\n\\r\\n` header terminator. If `stream.read` returns 0 — the peer closed the connection before sending complete headers — it bails with this error. It is a guard against truncated/malformed requests from misbehaving clients.","triggerScenarios":"A client opens a TCP connection to the local HTTP endpoint and closes it (or the connection drops) before sending the full request headers; a health-check probe that connects and disconnects; a port scanner or half-open connection timing out.","commonSituations":"Load balancer or monitoring health checks that only test TCP connect; curl aborted with Ctrl-C mid-request; network interruption between the client and the locally spawned server; a client sending a request smaller than the buffer read granularity that stalls and gets reset.","solutions":["Retry the request from the client once the connection is stable.","Identify clients that probe with connect-then-close and configure them to send a real HTTP request (e.g. `GET /health`).","If it occurs from your own code, ensure the client writes and flushes the full request before closing the socket."],"exampleFix":"// before (client closes early)\nlet mut s = TcpStream::connect(addr)?;\ndrop(s); // EOF on server\n\n// after\nlet mut s = TcpStream::connect(addr)?;\nwrite!(s, \"GET /health HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n\")?;","handlingStrategy":"try-catch","validationCode":"// Client: ensure the request is fully written before any early return/close\nassert!(request.contains(\"\\r\\n\\r\\n\"), \"request missing header terminator\");","typeGuard":null,"tryCatchPattern":"// Server caller side\nmatch read_http_request(&mut stream) {\n    Ok(req) => handle(req),\n    Err(e) if e.to_string().contains(\"Unexpected EOF\") => {\n        log::debug!(\"client closed connection early: {e}\"); // non-fatal, drop connection\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Configure health checks to send a real HTTP request rather than connect-and-close probes.","Retry idempotent requests on transient connection drops.","Monitor logs: isolated EOFs are noise; a burst indicates a client or network problem."],"tags":["http","network","rust"],"backgroundTag":"broken-pipe","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}