affaan-m/ECC · warning · anyhow::Error

Unexpected EOF while reading HTTP request body

Error message

Unexpected EOF while reading HTTP request body

What it means

After parsing headers, the reader continues pulling from the socket until the body reaches the `Content-Length` byte count. If the stream returns 0 (client disconnected) before the body is complete, it bails with this error. It distinguishes truncated request bodies from header-phase EOFs.

Solutions

  1. Retry the request from the client.
  2. Ensure the client's declared `Content-Length` exactly matches the bytes it writes.
  3. Check network/proxy stability for large request bodies; consider `Transfer-Encoding: chunked` via a full HTTP client instead of raw sockets.
  4. If your client is hand-written, flush the entire body before closing the stream.

Example fix

// before (client)
write!(s, "Content-Length: 100\r\n\r\n")?;
s.write_all(short_body)?; // fewer than 100 bytes

// after
write!(s, "Content-Length: {}\r\n\r\n", body.len())?;
s.write_all(&body)?;
Defensive patterns

Strategy: retry

Validate before calling

// Client: ensure Content-Length matches the body exactly
assert_eq!(body.len(), declared_content_length);

Try / catch

match send_request_with_body(req, body) {
    Err(e) if e.to_string().contains("Unexpected EOF") => {
        // transient drop: retry with backoff
        retry_with_backoff(3, || send_request_with_body(req, body))
    }
    other => other,
}

Prevention

When it happens

Trigger: A client sends a `Content-Length: N` header but closes the connection after transmitting fewer than N body bytes — aborted uploads, dropped connections mid-POST, or a client that lied about content length.

Common situations: User cancels a large POST/upload halfway; flaky network drops the TCP connection during a request body transfer; a hand-rolled HTTP client that sets `Content-Length` incorrectly; a proxy timing out and severing the upstream connection.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/acf09cb8bd72311b. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/main.rs:4244

    let mut headers = BTreeMap::new();
    for line in lines {
        if line.is_empty() {
            break;
        }
        if let Some((key, value)) = line.split_once(':') {
            headers.insert(key.trim().to_ascii_lowercase(), value.trim().to_string());
        }
    }

    let content_length = headers
        .get("content-length")
        .and_then(|value| value.parse::<usize>().ok())
        .unwrap_or(0);
    let mut body = buffer[header_end..].to_vec();
    while body.len() < content_length {
        let read = stream.read(&mut temp)?;
        if read == 0 {
            anyhow::bail!("Unexpected EOF while reading HTTP request body");
        }
        body.extend_from_slice(&temp[..read]);
    }
    body.truncate(content_length);

    Ok((method, path, headers, body))
}

fn write_http_response(
    stream: &mut TcpStream,
    status: u16,
    content_type: &str,
    body: &str,
) -> Result<()> {
    let status_text = match status {
        200 => "OK",
        202 => "Accepted",
        400 => "Bad Request",

View on GitHub (pinned to 8321021c54)