{"record":{"id":"0270f5466654a459","repo":"tokio-rs/tokio","slug":"task-was-cancelled","errorCode":null,"errorMessage":"task was cancelled","messagePattern":"task was cancelled","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"tokio/src/runtime/task/error.rs","lineNumber":173,"sourceCode":"impl fmt::Debug for JoinError {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match &self.repr {\n            Repr::Cancelled => write!(fmt, \"JoinError::Cancelled({:?})\", self.id),\n            Repr::Panic(p) => match panic_payload_as_str(p) {\n                Some(panic_str) => {\n                    write!(fmt, \"JoinError::Panic({:?}, {:?}, ...)\", self.id, panic_str)\n                }\n                None => write!(fmt, \"JoinError::Panic({:?}, ...)\", self.id),\n            },\n        }\n    }\n}\n\nimpl std::error::Error for JoinError {}\n\nimpl From<JoinError> for io::Error {\n    fn from(src: JoinError) -> io::Error {\n        io::Error::new(\n            io::ErrorKind::Other,\n            match src.repr {\n                Repr::Cancelled => \"task was cancelled\",\n                Repr::Panic(_) => \"task panicked\",\n            },\n        )\n    }\n}\n\nfn panic_payload_as_str(payload: &SyncWrapper<Box<dyn Any + Send>>) -> Option<&str> {\n    // Panic payloads are almost always `String` (if invoked with formatting arguments)\n    // or `&'static str` (if invoked with a string literal).\n    //\n    // Non-string panic payloads have niche use-cases,\n    // so we don't really need to worry about those.\n    if let Some(s) = payload.downcast_ref_sync::<String>() {\n        return Some(s);\n    }","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/tokio-rs/tokio/blob/625954f365727668cb02d04172b34f1149637728/tokio/src/runtime/task/error.rs#L155-L191","documentation":"From<JoinError> for io::Error maps Repr::Cancelled to the message 'task was cancelled'. It occurs when code converts a JoinError (from a JoinHandle whose task was cancelled) into an io::Error, typically via ? on a JoinHandle in a function returning io::Result.","triggerScenarios":"Awaiting a JoinHandle whose task was aborted via handle.abort() or cancelled during runtime shutdown, then propagating it as io::Error.","commonSituations":"Calling task.abort() and then awaiting the JoinHandle in a function returning io::Result; runtime shutdown cancelling outstanding tasks; select! that aborts a branch then awaits its handle.","solutions":["Before awaiting, check handle.is_finished() or match on the JoinError to distinguish cancellation from panic.","Avoid converting JoinError to io::Error wholesale; handle Err(JoinError) explicitly.","Don't abort tasks whose results you still need; use a cancellation token (CancellationToken) for cooperative cancellation.","Catch the cancelled branch in select! instead of awaiting it afterward."],"exampleFix":"// before\nlet r = handle.await?; // converts JoinError -> io::Error 'task was cancelled'\n// after\nmatch handle.await {\n    Ok(v) => v,\n    Err(e) if e.is_cancelled() => return,\n    Err(e) => return Err(e.into()),\n}","handlingStrategy":"try-catch","validationCode":"// Before awaiting, check whether the task was aborted.\nif handle.is_finished() { /* may be cancelled */ }","typeGuard":"// Distinguish JoinError variants before converting.\nfn is_cancelled(e: &tokio::task::JoinError) -> bool { e.is_cancelled() }","tryCatchPattern":"match handle.await {\n    Ok(v) => v,\n    Err(e) if e.is_cancelled() => {\n        // task was cancelled; handle gracefully\n        return;\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Match on JoinError instead of ?-converting to io::Error.","Use CancellationToken for cooperative cancellation.","Avoid aborting tasks whose result you still need."],"tags":["task","join-error","cancellation","io-error"],"backgroundTag":null,"analyzedSha":"625954f365727668cb02d04172b34f1149637728","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}