{"id":"566ae575e089d322","repo":"hyperium/hyper","slug":"http2-error","errorCode":null,"errorMessage":"http2 error","messagePattern":"http2 error","errorType":"exception","errorClass":"hyper::Error","httpStatus":null,"severity":"error","filePath":"src/error.rs","lineNumber":496,"sourceCode":"        Error::new(Kind::Shutdown).with(cause)\n    }\n\n    #[cfg(feature = \"ffi\")]\n    pub(super) fn new_user_aborted_by_callback() -> Error {\n        Error::new_user(User::AbortedByCallback)\n    }\n\n    #[cfg(all(feature = \"client\", any(feature = \"http1\", feature = \"http2\")))]\n    pub(super) fn new_user_dispatch_gone() -> Error {\n        Error::new(Kind::User(User::DispatchGone))\n    }\n\n    #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http2\"))]\n    pub(super) fn new_h2(cause: ::h2::Error) -> Error {\n        if cause.is_io() {\n            Error::new_io(cause.into_io().expect(\"h2::Error::is_io\"))\n        } else {\n            Error::new(Kind::Http2).with(cause)\n        }\n    }\n\n    fn description(&self) -> &str {\n        match self.inner.kind {\n            Kind::Parse(Parse::Method) => \"invalid HTTP method parsed\",\n            #[cfg(feature = \"http1\")]\n            Kind::Parse(Parse::Version) => \"invalid HTTP version parsed\",\n            #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http1\"))]\n            Kind::Parse(Parse::VersionH2) => \"invalid HTTP version parsed (found HTTP2 preface)\",\n            Kind::Parse(Parse::Uri) => \"invalid URI\",\n            #[cfg(all(feature = \"http1\", feature = \"server\"))]\n            Kind::Parse(Parse::UriTooLong) => \"URI too long\",\n            #[cfg(feature = \"http1\")]\n            Kind::Parse(Parse::Header(Header::Token)) => \"invalid HTTP header parsed\",\n            #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http1\"))]\n            Kind::Parse(Parse::Header(Header::ContentLengthInvalid)) => {\n                \"invalid content-length parsed\"","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/hyperium/hyper/blob/084473f728f9d07b3be5845475aa2f62ed9ff579/src/error.rs#L478-L514","documentation":"Thrown via Error::new_h2() (src/error.rs:492, Kind::Http2). It wraps an h2::Error from the HTTP/2 layer — a protocol, stream, or flow-control error reported by the h2 crate. (Note: if the h2 error is itself IO-backed, new_h2 routes it to Kind::Io instead — error.rs:493-495.) The real reason (h2::Reason such as INTERNAL_ERROR, ENHANCE_YOUR_CALM, NO_ERROR, PROTOCOL_ERROR) is in the source chain via h2_reason() (error.rs:353).","triggerScenarios":"Any h2::Error surfaced from the HTTP/2 state machine: stream reset, flow-control violation, GOAWAY from the peer, SETTINGS timeout, header too large for h2's max frame size. new_h2 wraps it (error.rs:496) unless cause.is_io().","commonSituations":"Server/client set inconsistent SETTINGS (e.g. max frame size, max header list size); peer sends GOAWAY; flow-control deadlock; a header list bigger than the peer's MAX_HEADER_LIST_SIZE (often surfaces as ENHANCE_YOUR_CALM); h2 version or feature mismatch between peers.","solutions":["Downcast the source to h2::Error and read .reason() (or use hyper's internal h2_reason) to get the precise h2::Reason before deciding.","If the reason is ENHANCE_YOUR_CALM / max header list, reduce header sizes or raise the peer's advertised h2 settings; for flow-control, check send/recv window config.","For NO_ERROR GOAWAY, reconnect and retry idempotent requests; for PROTOCOL_ERROR/INTERNAL_ERROR, treat the peer/connection as broken."],"exampleFix":"// before: opaque 'http2 error' with no diagnosis\nlet resp = client.get(uri).await?;\n\n// after: read the h2::Reason to drive recovery\nmatch client.get(uri.clone()).await {\n    Err(e) => {\n        if let Some(h2err) = e.source().and_then(|s| s.downcast_ref::<h2::Error>()) {\n            match h2err.reason() {\n                Some(h2::Reason::NO_ERROR) | Some(h2::Reason::CANCEL) => { /* reconnect + retry */ }\n                other => { /* log and fail */ }\n            }\n        }\n        return Err(e);\n    }\n    Ok(r) => Ok(r),\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn h2_reason(err: &hyper::Error) -> Option<h2::Reason> {\n    err.source()?.downcast_ref::<h2::Error>()?.reason()\n}","tryCatchPattern":"match client.get(uri.clone()).await {\n    Err(e) => {\n        if let Some(reason) = h2_reason(&e) {\n            match reason {\n                h2::Reason::NO_ERROR | h2::Reason::CANCEL | h2::Reason::REFUSED_STREAM => { /* retry */ }\n                h2::Reason::ENHANCE_YOUR_CALM => { /* reduce header/load */ }\n                _ => return Err(e),\n            }\n        } else { return Err(e); }\n    }\n    Ok(r) => return Ok(r),\n}","preventionTips":["Downcast the source to h2::Error and read .reason() before choosing recovery.","Keep header list sizes under the peer's MAX_HEADER_LIST_SIZE to avoid ENHANCE_YOUR_CALM.","Retry on NO_ERROR/REFUSED_STREAM with backoff; treat PROTOCOL_ERROR/INTERNAL_ERROR as fatal for that connection."],"tags":["http2","h2","protocol","flow-control","rust"],"analyzedSha":"084473f728f9d07b3be5845475aa2f62ed9ff579","analyzedAt":"2026-08-06T01:20:18.522Z","schemaVersion":2}