actix/actix-web · critical

Unsupported HTTP version: {:?}.

Error message

Unsupported HTTP version: {:?}.

What it means

In the HTTP service handler, incoming connections are dispatched by `Protocol`. At actix-http/src/service.rs:952-984 explicit arms handle `Http1` and (when the `http2` feature is on) `Http2`; any other protocol variant hits the catch-all `proto => unimplemented!(...)`, which panics. In practice this is reached only for protocol variants the build does not support (e.g. HTTP/2 connections when the `http2` feature is disabled at runtime via a custom Protocol, or future/unknown variants).

Source

Thrown at actix-http/src/service.rs:983

            #[cfg(not(feature = "http2"))]
            Protocol::Http2 => {
                panic!("HTTP/2 support is disabled (enable with the `http2` feature flag)")
            }

            Protocol::Http1 => HttpServiceHandlerResponse {
                state: State::H1 {
                    dispatcher: h1::Dispatcher::new(
                        io,
                        Rc::clone(&self.flow),
                        self.cfg.clone(),
                        peer_addr,
                        conn_data,
                    ),
                },
            },

            proto => unimplemented!("Unsupported HTTP version: {:?}.", proto),
        }
    }
}

#[cfg(not(feature = "http2"))]
pin_project! {
    #[project = StateProj]
    enum State<T, S, B, X, U>
    where
        T: AsyncRead,
        T: AsyncWrite,
        T: Unpin,

        S: Service<Request>,
        S::Future: 'static,
        S::Error: Into<Response<BoxBody>>,

        B: MessageBody,

View on GitHub (pinned to 937960ca67)

Solutions

  1. Ensure the `http2` feature is enabled in `Cargo.toml` if you serve HTTP/2: `actix-http = { version = "...", features = ["http2"] }`.
  2. Audit custom code/integrations that construct a `Protocol` and pass it to the service to confirm only Http1/Http2 are used.
  3. If you genuinely need another protocol, implement a dedicated handler arm upstream rather than relying on the catch-all.

Example fix

# before
# Cargo.toml
[dependencies]
actix-http = "4"

# after
[dependencies]
actix-http = { version = "4", features = ["http2"] }
Defensive patterns

Strategy: validation

Validate before calling

// Validate the protocol before dispatch (integration code only).
// Ensure only Http1/Http2 reach the service, and that the http2 feature is enabled.
fn is_supported(p: actix_http::Protocol) -> bool {
    matches!(p, actix_http::Protocol::Http1 | actix_http::Protocol::Http2)
}
// In Cargo.toml: actix-http = { features = ["http2"] }

Prevention

When it happens

Trigger: A connection arrives (or is injected) with a `Protocol` variant other than `Http1`/`Http2`, or HTTP/2 traffic reaches this arm while the `http2` cargo feature is compiled out (note: that specific case has its own clearer panic at line 968).

Common situations: Building actix-http with a restricted feature set, or a custom/integration layer that feeds an unsupported Protocol enum value into the service.

Related errors


AI-assisted analysis of actix/actix-web@937960ca67 (2026-08-06). Data as JSON: /data/errors/b865c0222576dfd4.json. Report an issue: GitHub.