hyperium/hyper · error · hyper::Error
connection closed before message completed
Error message
connection closed before message completed
What it means
Thrown via Error::new_incomplete() (src/error.rs:367, Kind::IncompleteMessage), gated behind feature="http1". It means the underlying IO reported EOF (a closed socket) while hyper's HTTP/1 state machine still expected more of the message — either the head or the body was only partially received. Detect it with Error::is_incomplete_message(). The hyper docs note common causes: a request sent on a connection whose next read is EOF (server closed an idle conn), a body cut short before Content-Length/chunk end, or a client that half-closes while you wait to respond.
Source
Thrown at src/error.rs:367
None
}
#[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))]
pub(super) fn h2_reason(&self) -> h2::Reason {
// Find an h2::Reason somewhere in the cause stack, if it exists,
// otherwise assume an INTERNAL_ERROR.
self.find_source::<h2::Error>()
.and_then(|h2_err| h2_err.reason())
.unwrap_or(h2::Reason::INTERNAL_ERROR)
}
pub(super) fn new_canceled() -> Error {
Error::new(Kind::Canceled)
}
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
pub(super) fn new_incomplete() -> Error {
Error::new(Kind::IncompleteMessage)
}
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
pub(super) fn new_too_large() -> Error {
Error::new(Kind::Parse(Parse::TooLarge))
}
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
pub(super) fn new_version_h2() -> Error {
Error::new(Kind::Parse(Parse::VersionH2))
}
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
pub(super) fn new_unexpected_message() -> Error {
Error::new(Kind::UnexpectedMessage)
}
#[cfg(all(View on GitHub (pinned to 084473f728)
Solutions
- Detect with Error::is_incomplete_message() and retry idempotent requests on a new connection rather than failing the user.
- If you are a server whose client half-closes while awaiting a response, enable http1 half_close on the server Builder so the connection can still complete.
- Tune keep-alive/idle timeouts on both peers so neither closes a connection the other is about to reuse, and drain bodies fully before returning.
Example fix
// before: incomplete message aborts the whole operation
let resp = client.get(uri).await?;
// after: retry on a fresh connection when the old one was cut mid-message
async fn fetch(client: &Client<...>, uri: Uri) -> Result<Response<Body>, hyper::Error> {
for attempt in 0..2u8 {
match client.get(uri.clone()).await {
Err(e) if e.is_incomplete_message() && attempt == 0 => continue,
res => return res,
}
}
unreachable!()
} Defensive patterns
Strategy: retry
Type guard
fn is_incomplete(err: &hyper::Error) -> bool {
err.is_incomplete_message()
} Try / catch
match client.get(uri.clone()).await {
Err(e) if e.is_incomplete_message() && idempotent => { /* retry on new connection */ }
other => other,
} Prevention
- Fully drain request bodies before returning a response on the server side.
- Enable http1 half_close on the server if clients half-close while awaiting a response.
- Align keep-alive/idle timeouts across peers so neither reaps a connection the other is about to reuse.
When it happens
Trigger: Reading the request/response head hits EOF before the terminating CRLF CRLF (proto/h1/io.rs:214, proto/h1/conn.rs:473 and :504); the dispatch sender is told the connection ended with an in-flight message (proto/h1/dispatch.rs:551). Happens when the peer closes the TCP stream partway through a request or response.
Common situations: An upstream reverse proxy/load balancer closes an idle keep-alive connection just as you send the next request; a client sends headers then closes the write half while the server is still computing a response (needs half_close enabled); a flaky mobile network drops the socket mid-body; a server with aggressive idle timeouts.
Related errors
- error reading a body from connection
- error shutting down connection
- end of file before message length reached
- unexpected EOF during chunk size line
- operation was canceled
AI-assisted analysis of hyperium/hyper@084473f728 (2026-08-06).
Data as JSON: /data/errors/6265313f5ad579c1.json.
Report an issue: GitHub.