hyperium/hyper · error · hyper::Error
connection error
Error message
connection error
What it means
Thrown via Error::new_io() (src/error.rs:390, Kind::Io). It wraps a std::io::Error that occurred while reading from or writing to the network stream — the generic 'something went wrong at the socket layer' variant. The real detail lives in the source chain (Error::source() downcast to std::io::Error): connection reset by peer, broken pipe, connection refused, TLS error, etc. Because it is the lowest-level IO bucket, the message alone is not enough — always inspect the source.
Source
Thrown at src/error.rs:390
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(
any(feature = "client", feature = "server"),
any(feature = "http1", feature = "http2")
))]
pub(super) fn new_io(cause: std::io::Error) -> Error {
Error::new(Kind::Io).with(cause)
}
#[cfg(any(
all(feature = "http1", any(feature = "client", feature = "server")),
all(feature = "http2", feature = "client")
))]
pub(super) fn new_closed() -> Error {
Error::new(Kind::ChannelClosed)
}
#[cfg(all(
any(feature = "client", feature = "server"),
any(feature = "http1", feature = "http2")
))]
pub(super) fn new_body<E: Into<Cause>>(cause: E) -> Error {
Error::new(Kind::Body).with(cause)
}
View on GitHub (pinned to 084473f728)
Solutions
- Inspect the source: downcast Error::source() to std::io::Error to get ErrorKind (UnexpectedEof, ConnectionReset, BrokenPipe, TimedOut, etc.) before deciding what to do.
- For transient kinds (ConnectionReset, BrokenPipe, UnexpectedEof) retry idempotent requests on a fresh connection.
- For connect-time failures, verify reachability (DNS, port, firewall, TLS) and add retries with backoff for the connection establishment step.
Example fix
// before: bubble up the opaque 'connection error'
let resp = client.get(uri).await?;
// after: classify the underlying io::Error to decide retry vs fail
match client.get(uri.clone()).await {
Err(e) => {
if let Some(io) = e.source().and_then(|s| s.downcast_ref::<std::io::Error>()) {
match io.kind() {
std::io::ErrorKind::ConnectionReset |
std::io::ErrorKind::UnexpectedEof => { /* retry idempotent */ }
_ => return Err(e),
}
} else { return Err(e); }
}
Ok(r) => return Ok(r),
} Defensive patterns
Strategy: retry
Type guard
fn underlying_io(err: &hyper::Error) -> Option<&std::io::Error> {
err.source()?.downcast_ref::<std::io::Error>()
}
fn is_transient_io(err: &hyper::Error) -> bool {
matches!(
underlying_io(err).map(|io| io.kind()),
Some(std::io::ErrorKind::ConnectionReset)
| Some(std::io::ErrorKind::BrokenPipe)
| Some(std::io::ErrorKind::UnexpectedEof)
| Some(std::io::ErrorKind::TimedOut)
| Some(std::io::ErrorKind::WouldBlock)
)
} Try / catch
for attempt in 0..3u8 {
match client.get(uri.clone()).await {
Ok(r) => return Ok(r),
Err(e) if attempt < 2 && is_transient_io(&e) && idempotent => {
tokio::time::sleep(backoff(attempt)).await;
continue;
}
Err(e) => return Err(e),
}
} Prevention
- Always downcast Error::source() to std::io::Error before deciding — the top-level message is generic.
- Retry only idempotent methods on transient io kinds; keep per-attempt and total timeouts.
- Verify DNS/port/TLS/firewall separately when the failure is at connect time.
When it happens
Trigger: Any read/write on the TcpStream (or TLS stream, or custom IO) returns an io::Error and hyper lifts it via new_io (error.rs:389). Also note the h2 path: new_h2 (error.rs:492) routes io-backed h2 errors here too (cause.is_io() branch). Fires on TCP RST, broken pipe after peer close, DNS/connect failures on the client, or a TLS handshake/alert.
Common situations: Peer crashed or network dropped mid-transfer (ECONNRESET/EOF); server process killed while client is reading; TLS misconfiguration surfacing as an IO error; a reverse proxy restarting; firewall/NAT dropping an idle connection with RST. Very common in any real networked deployment.
Related errors
- connection closed before message completed
- error reading a body from connection
- error writing a body to connection
- error shutting down connection
- keep-alive timed out
AI-assisted analysis of hyperium/hyper@084473f728 (2026-08-06).
Data as JSON: /data/errors/743de6b859044729.json.
Report an issue: GitHub.