hyperium/hyper · error · hyper::Error
invalid HTTP version parsed (found HTTP2 preface)
Error message
invalid HTTP version parsed (found HTTP2 preface)
What it means
Thrown via Error::new_version_h2() (src/error.rs:377, Kind::Parse(Parse::VersionH2)), HTTP/1-only feature. It is produced in Conn::on_parse_error (proto/h1/conn.rs:821) specifically when the connection's read buffer starts with the HTTP/2 connection preface (H2_PREFACE = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", conn.rs:29, detected by has_h2_prefix at conn.rs:206). It means the peer spoke HTTP/2 to a listener configured for HTTP/1 only. Detect with Error::is_parse_version_h2().
Source
Thrown at src/error.rs:377
}
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(
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")View on GitHub (pinned to 084473f728)
Solutions
- Enable HTTP/2 on the listener (enable the http2 feature and build the server with the h2 handshake) so the preface is handled instead of rejected.
- If you only support HTTP/1, configure the client to use HTTP/1 (e.g. http2_only(false) / http1_only) so it never sends the preface.
- For TLS, set ALPN correctly (e.g. ["h2", "http/1.1"]) so negotiation lands on a mutually supported protocol.
Example fix
// before: server only speaks HTTP/1, rejects HTTP/2 clients
let mut http = hyper::server::conn::Http::new(); // http1 only
// after: enable HTTP/2 so the preface is accepted
// (requires the "http2" cargo feature)
let make_svc = hyper::server::conn::auto::Builder::new(tokio_io)
.serve_connection(stream, svc); Defensive patterns
Strategy: validation
Validate before calling
// Decide protocol up front and build the matching server/client.
// For TLS, configure ALPN so negotiation is authoritative:
let alpn = tokio_rustls::rustls::ServerConfig::builder()
.with_no_client_auth()
.with_protocols(&[b"h2" as &[u8], b"http/1.1"])
.into(); Type guard
fn is_h2_preface_on_h1(err: &hyper::Error) -> bool {
err.is_parse_version_h2()
} Try / catch
match serve_connection(...).await {
Err(e) if e.is_parse_version_h2() => {
// peer needs h2; rebuild this listener with the http2 feature / auto Builder
}
other => other,
} Prevention
- Enable the http2 cargo feature on both peers that must speak h2.
- Use server::conn::auto::Builder when a listener must accept both h1 and h2.
- Set ALPN correctly on TLS so the client and server agree on protocol before bytes flow.
When it happens
Trigger: An HTTP/2 client connects to a plain HTTP/1 server (no TLS ALPN, no h2 in the server Builder); a service built with Http::new() (http1 only) receives the PRI/SM preface; ALPN negotiated h2 but the server was only built for http1. The 24-byte preface is matched in conn.rs:208.
Common situations: Mixing up http1/http2 feature flags in Cargo (server built without the http2 feature, or only http1 enabled); a client hard-coded to h2 hitting an http1 endpoint; a reverse proxy upstreaming h2 to an h1 backend; misconfigured ALPN where the listener speaks h1 but the client chose h2.
Related errors
- operation was canceled
- error reading a body from connection
- connection closed before message completed
- message head is too large
- received unexpected message from connection
AI-assisted analysis of hyperium/hyper@084473f728 (2026-08-06).
Data as JSON: /data/errors/a95da77278d269ff.json.
Report an issue: GitHub.