{"record":{"id":"d6fc95569561daa1","repo":"tokio-rs/tokio","slug":"blocking-pool-shutting-down","errorCode":null,"errorMessage":"blocking pool shutting down","messagePattern":"blocking pool shutting down","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"tokio/src/runtime/blocking/pool.rs","lineNumber":208,"sourceCode":"        allow(dead_code)\n    )]\n    Mandatory,\n    NonMandatory,\n}\n\npub(crate) enum SpawnError {\n    /// Pool is shutting down and the task was not scheduled\n    ShuttingDown,\n    /// There are no worker threads available to take the task\n    /// and the OS failed to spawn a new one\n    NoThreads(io::Error),\n}\n\nimpl From<SpawnError> for io::Error {\n    fn from(e: SpawnError) -> Self {\n        match e {\n            SpawnError::ShuttingDown => {\n                io::Error::new(io::ErrorKind::Other, \"blocking pool shutting down\")\n            }\n            SpawnError::NoThreads(e) => e,\n        }\n    }\n}\n\nimpl Task {\n    pub(crate) fn new(task: task::UnownedTask<BlockingSchedule>, mandatory: Mandatory) -> Task {\n        Task { task, mandatory }\n    }\n\n    pub(super) fn shutdown(self) {\n        self.task.shutdown();\n    }\n\n    pub(super) fn run(self) {\n        self.task.run();\n    }","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/tokio-rs/tokio/blob/7d0d729d8f03a0033d6752730d0fb5928962560e/tokio/src/runtime/blocking/pool.rs#L190-L226","documentation":"SpawnError::ShuttingDown surfaced as an io::Error with kind Other. It is produced when the runtime's blocking thread pool (used by spawn_blocking and internal blocking ops) has already begun shutdown and therefore refuses to schedule a new blocking task. The From<SpawnError> impl converts it into the generic io::Error shown.","triggerScenarios":"Calling spawn_blocking (or any API that schedules onto the blocking pool, e.g. some fs operations after shutdown) after the runtime has been dropped or shut down; spawning blocking work from a task whose runtime handle outlives the pool's shutdown.","commonSituations":"Storing a Handle and using it after Runtime::drop; spawning blocking work from a Drop impl or a background thread that races runtime teardown; using #[tokio::main] and awaiting work past the function's runtime lifetime.","solutions":["Ensure spawn_blocking calls happen while the runtime is still alive — structure shutdown so blocking tasks drain before Runtime::drop.","Keep a runtime guard (Runtime) alive for the full duration blocking work may be submitted.","Use Handle::is_alive / handle the Err from spawn_blocking to degrade gracefully.","Avoid submitting blocking work from Drop impls that may run during teardown."],"exampleFix":"// before\nlet handle = runtime.handle().clone();\ndrop(runtime);\nhandle.spawn_blocking(|| { /* ... */ }); // fails\n// after\nlet jh = runtime.spawn_blocking(|| { /* ... */ });\njh.await?; // drain before dropping runtime\ndrop(runtime);","handlingStrategy":"validation","validationCode":"// Validate the runtime/driver is alive before spawning blocking work.\nif handle.runtime_flavor() == RuntimeFlavor::CurrentThread && /* runtime dropped */ {\n    return Err(io::Error::new(io::ErrorKind::Other, \"runtime gone\"));\n}\n// Prefer: spawn early and hold the JoinHandle.","typeGuard":null,"tryCatchPattern":"match runtime.spawn_blocking(|| expensive()) {\n    _ => {} // spawn_blocking itself returns a JoinHandle, not Result; the error surfaces on .await\n}\n// On .await:\nmatch jh.await {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"shutting down\") => return,\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Own the Runtime for the full lifetime of any blocking task.","Drain blocking JoinHandles before dropping the runtime.","Avoid spawn_blocking from Drop impls."],"tags":["runtime","blocking-pool","spawn-blocking","shutdown","io-error"],"backgroundTag":null,"analyzedSha":"7d0d729d8f03a0033d6752730d0fb5928962560e","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}