{"id":"ad40d9e71689a1cc","repo":"hyperium/hyper","slug":"received-unexpected-message-from-connection","errorCode":null,"errorMessage":"received unexpected message from connection","messagePattern":"received unexpected message from connection","errorType":"exception","errorClass":"hyper::Error","httpStatus":null,"severity":"error","filePath":"src/error.rs","lineNumber":382,"sourceCode":"\n    #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http1\"))]\n    pub(super) fn new_incomplete() -> Error {\n        Error::new(Kind::IncompleteMessage)\n    }\n\n    #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http1\"))]\n    pub(super) fn new_too_large() -> Error {\n        Error::new(Kind::Parse(Parse::TooLarge))\n    }\n\n    #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http1\"))]\n    pub(super) fn new_version_h2() -> Error {\n        Error::new(Kind::Parse(Parse::VersionH2))\n    }\n\n    #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http1\"))]\n    pub(super) fn new_unexpected_message() -> Error {\n        Error::new(Kind::UnexpectedMessage)\n    }\n\n    #[cfg(all(\n        any(feature = \"client\", feature = \"server\"),\n        any(feature = \"http1\", feature = \"http2\")\n    ))]\n    pub(super) fn new_io(cause: std::io::Error) -> Error {\n        Error::new(Kind::Io).with(cause)\n    }\n\n    #[cfg(any(\n        all(feature = \"http1\", any(feature = \"client\", feature = \"server\")),\n        all(feature = \"http2\", feature = \"client\")\n    ))]\n    pub(super) fn new_closed() -> Error {\n        Error::new(Kind::ChannelClosed)\n    }\n","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/hyperium/hyper/blob/084473f728f9d07b3be5845475aa2f62ed9ff579/src/error.rs#L364-L400","documentation":"Thrown via Error::new_unexpected_message() (src/error.rs:382, Kind::UnexpectedMessage), HTTP/1 only. It means the connection delivered a full new message (request or response) at a point in the state machine where none was expected — e.g. the server already moved on or the client got a second response head while not pipelining. Produced at proto/h1/conn.rs:465 and :488, and proto/h1/dispatch.rs:712.","triggerScenarios":"A client receives a response head while hyper is not waiting for one (conn.rs:465/488); the HTTP/1 dispatch loop gets a message when it expected a body continuation or idle (dispatch.rs:712). Often tied to an ill-behaved peer sending extra data, or a keep-alive reuse race after an error.","commonSituations":"A server that pipelines responses incorrectly; a buggy proxy injecting an extra response; a peer that sends a second request head inside what hyper thought was a body; protocol confusion after a 101 Upgrade or an informational response.","solutions":["Capture the peer's exact bytes with a packet capture (tcpdump/wireshark) to confirm it is sending data outside the expected HTTP/1 framing.","If you control the peer, fix its request/response sequencing; otherwise treat the connection as corrupt and close it.","Disable HTTP/1 pipelining assumptions and reuse the connection conservatively (open a fresh connection after such an error)."],"exampleFix":"// before: any connection error terminates the whole client\nlet resp = sender.send_request(req).await?;\n\n// after: drop the corrupt connection and start a new one\nmatch sender.send_request(req).await {\n    Err(e) => {\n        if !e.is_incomplete_message() {\n            // unexpected_message etc. => connection is unusable, reconnect\n        }\n        return Err(e);\n    }\n    Ok(r) => Ok(r),\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// UnexpectedMessage isn't exposed as is_*(); match the description/source only\n// for logging — do NOT depend on the string. Treat unknown connection errors\n// as fatal for that connection.\nfn is_connection_corrupt(_e: &hyper::Error) -> bool { /* not stable to detect */ false }","tryCatchPattern":"if let Err(e) = sender.send_request(req).await {\n    // unexpected_message means the connection framing is broken\n    drop_connection_and_reconnect();\n    return Err(e);\n}","preventionTips":["After any unexpected-message error, never reuse that connection — open a new one.","Disable assumptions about HTTP/1 pipelining on either side.","Capture the wire bytes when this recurs to find the peer that mis-sequences messages."],"tags":["http1","protocol","framing","rust"],"analyzedSha":"084473f728f9d07b3be5845475aa2f62ed9ff579","analyzedAt":"2026-08-06T01:20:18.522Z","schemaVersion":2}