{"record":{"id":"7d902e064639b628","repo":"tokio-rs/tokio","slug":"a-tokio-1-x-context-was-found-but-it-is-being-shutdown","errorCode":null,"errorMessage":"A Tokio 1.x context was found, but it is being shutdown.","messagePattern":"A Tokio 1\\.x context was found, but it is being shutdown\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tokio/src/runtime/time_alt/timer.rs","lineNumber":37,"sourceCode":"}\n\nimpl Drop for Timer {\n    fn drop(&mut self) {\n        self.entry.cancel();\n    }\n}\n\nimpl Timer {\n    #[track_caller]\n    pub(crate) fn new(handle: scheduler::Handle, deadline: u64) -> Self {\n        let entry = with_current_temp_local_context(&handle, |ctx| match ctx {\n            Some(TempLocalContext::Running { registration_queue }) => {\n                let entry = EntryHandle::new(deadline);\n                unsafe { registration_queue.push_front(entry.clone()) }\n                entry\n            }\n            #[cfg(feature = \"rt-multi-thread\")]\n            Some(TempLocalContext::Shutdown) => panic!(\"{RUNTIME_SHUTTING_DOWN_ERROR}\"),\n\n            _ => {\n                let entry = EntryHandle::new(deadline);\n                push_from_remote(&handle, entry.clone());\n                entry\n            }\n        });\n\n        Timer { entry }\n    }\n\n    pub(crate) fn is_elapsed(&self) -> bool {\n        self.entry.is_woken_up()\n    }\n\n    pub(crate) fn poll_elapsed(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {\n        self.entry.poll(cx)\n    }","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/tokio-rs/tokio/blob/8146318256a83c892fcc7f43a41f66389a892669/tokio/src/runtime/time_alt/timer.rs#L19-L55","documentation":"This panic comes from Tokio's timer when code attempts to register a timer (create a Sleep/Interval or drive timer entries) while the Tokio runtime is in the middle of shutting down. A Tokio 1.x context was found on the thread, but it is marked TempLocalContext::Shutdown, so the timer's registration queue can no longer accept new entries and the library panics with RUNTIME_SHUTTING_DOWN_ERROR instead of silently misbehaving. It is a library invariant check: timers must never be created or registered after shutdown has begun.","triggerScenarios":"Creating a timer primitive (tokio::time::sleep, sleep_until, interval, Timeout, timer EntryHandle::new) or otherwise entering the timer driver when the thread-local context is TempLocalContext::Shutdown — i.e. after Runtime::shutdown or during runtime teardown. Typical concrete calls: tokio::time::sleep(...) or a future containing it being polled/spawned from within a Drop impl, a thread-local destructor, or block_on executed after the runtime has begun shutting down.","commonSituations":"Dropping values that call sleep/cancel timers in their Drop impls while the runtime shuts down; spawning or awaiting timers from tokio::task::block_in_place or from a plain std thread using a Handle whose runtime is shutting down; calling runtime.block_on() again after shutdown_timeout/shutdown_background; holding a Runtime in a static or thread-local that is torn down after the runtime; ordering bugs where a shutdown_timeout is too short and tasks still call time APIs during teardown.","solutions":["Ensure the Runtime outlives every timer user: keep the Runtime value alive until all tasks/futures using tokio::time have completed, and drop timer-holding values before calling shutdown.","Use runtime.shutdown_timeout(Duration) or shutdown_background instead of a bare drop/shutdown so pending tasks get drained and stop calling timer APIs mid-teardown.","Remove time API calls (sleep, interval, Timeout) from Drop implementations and thread-local destructors; defer cleanup work to a spawned task before shutdown.","Do not call block_on on a runtime after shutdown has started; spawn post-shutdown work on a different runtime or executor.","If work must continue past runtime shutdown, clone a tokio::runtime::Handle and use it on a runtime that is guaranteed alive, or run the work with std::thread::sleep instead of tokio::time::sleep."],"exampleFix":"// before: runtime dropped/shutdown while a spawned task still sleeps\nlet rt = tokio::runtime::Runtime::new().unwrap();\nrt.spawn(async { tokio::time::sleep(Duration::from_secs(10)).await; });\ndrop(rt); // shutdown begins; task polls sleep -> panic: context is being shutdown\n\n// after: give tasks time to finish before teardown\nlet rt = tokio::runtime::Runtime::new().unwrap();\nrt.spawn(async { tokio::time::sleep(Duration::from_secs(10)).await; });\nrt.shutdown_timeout(Duration::from_secs(15)); // drains tasks, no panic","handlingStrategy":"try-catch","validationCode":"// Rust: this is a panic, not a Result; ensure a live runtime context before timer use\nlet handle = tokio::runtime::Handle::try_current();\nassert!(handle.is_ok(), \"timer APIs require a live Tokio runtime context\");\n// and do not create timers after shutdown: keep the Runtime alive while\n// any future using tokio::time is polled.","typeGuard":null,"tryCatchPattern":"// Panics are not catchable with normal error handling; guard with catch_unwind only as a last resort\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    rt.block_on(async { tokio::time::sleep(std::time::Duration::from_secs(1)).await; })\n}));\nif result.is_err() {\n    eprintln!(\"timer used during runtime shutdown\");\n}","preventionTips":["Keep the Runtime alive until all tasks that use tokio::time have finished; prefer shutdown_timeout over drop.","Never call tokio::time APIs (sleep, interval, Timeout) from Drop impls or thread-local destructors.","Clone the runtime Handle into background tasks so ownership makes runtime lifetime explicit.","Do not reuse a Runtime with block_on after calling shutdown/shutdown_background.","Increase shutdown_timeout if tasks perform timed waits during teardown."],"tags":["rust","tokio","async","timer","runtime-shutdown","panic"],"backgroundTag":"runtime-shutdown-in-progress","analyzedSha":"8146318256a83c892fcc7f43a41f66389a892669","analyzedAt":"2026-09-14T11:25:15.498Z","contentChangedAt":"2026-09-14T11:25:15.498Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}