{"id":"d2085c8c200beb11","repo":"hyperium/hyper","slug":"operation-was-canceled","errorCode":null,"errorMessage":"operation was canceled","messagePattern":"operation was canceled","errorType":"exception","errorClass":"hyper::Error","httpStatus":null,"severity":"warning","filePath":"src/error.rs","lineNumber":362,"sourceCode":"            }\n            cause = err.source();\n        }\n\n        // else\n        None\n    }\n\n    #[cfg(all(any(feature = \"client\", feature = \"server\"), feature = \"http2\"))]\n    pub(super) fn h2_reason(&self) -> h2::Reason {\n        // Find an h2::Reason somewhere in the cause stack, if it exists,\n        // otherwise assume an INTERNAL_ERROR.\n        self.find_source::<h2::Error>()\n            .and_then(|h2_err| h2_err.reason())\n            .unwrap_or(h2::Reason::INTERNAL_ERROR)\n    }\n\n    pub(super) fn new_canceled() -> Error {\n        Error::new(Kind::Canceled)\n    }\n\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\"))]","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/hyperium/hyper/blob/084473f728f9d07b3be5845475aa2f62ed9ff579/src/error.rs#L344-L380","documentation":"Thrown via Error::new_canceled() (src/error.rs:362, Kind::Canceled). It means a pending request/response operation was dropped or the connection went away before the operation could be dispatched or completed. hyper does not consider this a hard protocol failure — it is reported distinctly and you can detect it with Error::is_canceled(). In practice it is often benign (the caller no longer cares about the result), but it can also surface when the underlying connection died while a request was queued.","triggerScenarios":"Calling send_request on a client::conn SendRequest and dropping the returned Response future before it resolves; the HTTP/1 dispatch loop seeing the connection close while a request is still queued (proto/h1/dispatch.rs:729, .with(\"connection closed\")); a client send_request that finds the connection 'was not ready' and exhausts its retry (client/conn/http1.rs:229, client/conn/http2.rs:167).","commonSituations":"A request future is abandoned because a wrapping timeout (tokio::time::timeout) elapsed and dropped it; a single shared connection is reused across many concurrent tasks and one task is cancelled; an upstream is slow and the caller gives up. Usually appears alongside a tokio cancel/cancellation.","solutions":["Check Error::is_canceled() and treat it as non-fatal — for idempotent requests, retry on a fresh connection rather than propagating.","If you intentionally drop response futures (e.g. fire-and-forget), expect and ignore this variant explicitly instead of logging it as an error.","If cancellations are unexpected, audit the call site for a wrapping timeout, a Select that drops the losing branch, or a connection pool evicting an idle connection mid-request."],"exampleFix":"// before: any error is fatal\nlet resp = client.get(uri).await?;\n\n// after: distinguish cancellation from real errors\nmatch client.get(uri).await {\n    Ok(resp) => { /* ... */ }\n    Err(e) if e.is_canceled() => {\n        // request was dropped / connection closed mid-flight; retry idempotent calls\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// hyper exposes the predicate directly; wrap for readability\nfn is_canceled(err: &hyper::Error) -> bool {\n    err.is_canceled()\n}","tryCatchPattern":"match client.get(uri).await {\n    Ok(resp) => { /* handle */ }\n    Err(e) if e.is_canceled() => { /* dropped/disconnected mid-flight: retry idempotent */ }\n    Err(e) => return Err(e),\n}","preventionTips":["Decide explicitly whether each response future may be dropped; if so, expect and ignore is_canceled().","Use a dedicated retry layer (e.g. tower::retry) keyed on is_canceled() for idempotent verbs.","Don't share a single connection across tasks whose lifetimes you don't control; use a pool that can reopen."],"tags":["client","cancellation","http1","http2","rust"],"analyzedSha":"084473f728f9d07b3be5845475aa2f62ed9ff579","analyzedAt":"2026-08-06T01:20:18.522Z","schemaVersion":2}