{"id":"a679c309d2885974","repo":"hyperium/hyper","slug":"channel-closed","errorCode":null,"errorMessage":"channel closed","messagePattern":"channel closed","errorType":"exception","errorClass":"hyper::Error","httpStatus":null,"severity":"warning","filePath":"src/error.rs","lineNumber":398,"sourceCode":"    #[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\n    #[cfg(all(\n        any(feature = \"client\", feature = \"server\"),\n        any(feature = \"http1\", feature = \"http2\")\n    ))]\n    pub(super) fn new_body<E: Into<Cause>>(cause: E) -> Error {\n        Error::new(Kind::Body).with(cause)\n    }\n\n    #[cfg(all(\n        any(feature = \"client\", feature = \"server\"),\n        any(feature = \"http1\", feature = \"http2\")\n    ))]\n    pub(super) fn new_body_write<E: Into<Cause>>(cause: E) -> Error {\n        Error::new(Kind::BodyWrite).with(cause)\n    }\n","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/hyperium/hyper/blob/084473f728f9d07b3be5845475aa2f62ed9ff579/src/error.rs#L380-L416","documentation":"Thrown via Error::new_closed() (src/error.rs:398, Kind::ChannelClosed). It indicates the other end of an internal mpsc/watch channel was dropped: either the dispatch task (client side) or the body sender/receiver. Detect with Error::is_closed(). It usually means a producer or consumer went away — for a client it can mean the connection task ended; for a body it means the reader stopped polling.","triggerScenarios":"Client send_request fails because the dispatch sender was dropped (client/dispatch.rs:79); a Body sender's channel receiver was dropped (body/incoming.rs:367/374/391/399/401); an HTTP/2 client stream's channel closed (client/conn/http2.rs:99).","commonSituations":"The connection-driving future was dropped (task cancelled) while you still hold a SendRequest handle; a streaming body producer was dropped before sending the end; a client is reused after its background connection task already finished; backpressure where the consumer is gone.","solutions":["Detect with Error::is_closed() and create a brand-new connection/client rather than reusing the dead handle.","Ensure the future that drives the connection (the one yielded by client::conn::http1::handshake) stays alive for as long as you use the SendRequest handle.","For streaming bodies, make sure the body future isn't dropped prematurely, and finish sending (or abort intentionally) before the consumer disappears."],"exampleFix":"// before: reuse a client handle whose connection task already ended\nlet resp = sender.send_request(req).await?; // Err: channel closed\n\n// after: rebuild the connection when the channel is gone\nmatch sender.send_request(req).await {\n    Err(e) if e.is_closed() => {\n        let (new_sender, conn) = hyper::client::conn::http1::handshake(stream).await?;\n        tokio::spawn(conn);\n        // retry with new_sender ...\n    }\n    other => other,\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":"fn is_channel_closed(err: &hyper::Error) -> bool {\n    err.is_closed()\n}","tryCatchPattern":"match sender.send_request(req).await {\n    Err(e) if e.is_closed() => {\n        let (sender, conn) = hyper::client::conn::http1::handshake(new_stream()).await?;\n        tokio::spawn(conn);\n        // retry with the fresh sender\n    }\n    other => return other,\n}","preventionTips":["Spawn the connection future from handshake immediately so it outlives the handle.","Detect is_closed() and rebuild the connection rather than reusing a dead handle.","Keep body producers alive until they finish or are intentionally aborted."],"tags":["channel","client","body","lifecycle","rust"],"analyzedSha":"084473f728f9d07b3be5845475aa2f62ed9ff579","analyzedAt":"2026-08-06T01:20:18.522Z","schemaVersion":2}