{"record":{"id":"91dfd597a45d8c3e","repo":"tokio-rs/tokio","slug":"unhandled-panic-behavior-modified-after-starting-l","errorCode":null,"errorMessage":"Unhandled Panic behavior modified after starting LocalSet","messagePattern":"Unhandled Panic behavior modified after starting LocalSet","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tokio/src/task/local.rs","lineNumber":927,"sourceCode":"        ///     .run_until(async {\n        ///         tokio::task::spawn_local(async { panic!(\"boom\"); });\n        ///         tokio::task::spawn_local(async {\n        ///             // This task never completes\n        ///         });\n        ///\n        ///         // Do some work, but `run_until` will panic before it completes\n        /// # loop { tokio::task::yield_now().await; }\n        ///     })\n        ///     .await;\n        /// # }\n        /// ```\n        ///\n        /// [`JoinHandle`]: struct@crate::task::JoinHandle\n        pub fn unhandled_panic(&mut self, behavior: crate::runtime::UnhandledPanic) -> &mut Self {\n            // TODO: This should be set as a builder\n            Rc::get_mut(&mut self.context)\n                .and_then(|ctx| Arc::get_mut(&mut ctx.shared))\n                .expect(\"Unhandled Panic behavior modified after starting LocalSet\")\n                .unhandled_panic = behavior;\n            self\n        }\n    }\n}\n\nimpl fmt::Debug for LocalSet {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"LocalSet\").finish()\n    }\n}\n\nimpl Future for LocalSet {\n    type Output = ();\n\n    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {\n        let _no_blocking = crate::runtime::context::disallow_block_in_place();\n","sourceCodeStart":909,"sourceCodeEnd":945,"githubUrl":"https://github.com/tokio-rs/tokio/blob/7d0d729d8f03a0033d6752730d0fb5928962560e/tokio/src/task/local.rs#L909-L945","documentation":"LocalSet::unhandled_panic uses Rc::get_mut(...).and_then(Arc::get_mut).expect(...) to mutate the shared context. Rc::get_mut returns None when there are other strong references to the context — which happens once the LocalSet has started running (it has been cloned into the runtime). Thus configuring unhandled_panic after the LocalSet is running is rejected.","triggerScenarios":"Calling .unhandled_panic(behavior) on a LocalSet after it has been entered/run via run_until/run/block_on, or after tasks have been spawned onto it.","commonSituations":"Constructing a LocalSet, spawning tasks, then trying to change unhandled_panic behavior; sharing the LocalSet across structures before configuring it.","solutions":["Set unhandled_panic BEFORE spawning any tasks or running the LocalSet.","Configure it immediately after LocalSet::new() while the Rc has a single owner.","If reconfiguration is needed, create a new LocalSet with the desired behavior and migrate.","Treat unhandled_panic as a build-time/construct-time setting, not a runtime toggle."],"exampleFix":"// before\nlet ls = LocalSet::new();\nls.spawn_local(async { /* ... */ });\nls.unhandled_panic(UnhandledPanic::Shutdown); // panics: already running\n// after\nlet mut ls = LocalSet::new();\nls.unhandled_panic(UnhandledPanic::Shutdown); // before any spawn/run\nls.spawn_local(async { /* ... */ });","handlingStrategy":"validation","validationCode":"// Set unhandled_panic before any spawn/run:\nlet mut ls = tokio::task::LocalSet::new();\nls.unhandled_panic(tokio::runtime::UnhandledPanic::Shutdown);\n// only now spawn/run","typeGuard":null,"tryCatchPattern":"// No catch needed if you follow the contract; defensive catch_unwind:\nstd::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    ls.unhandled_panic(behavior);\n})).map_err(|_| io::Error::new(io::ErrorKind::Other, \"already running\"))?","preventionTips":["Configure unhandled_panic immediately after new().","Never mutate it after spawn_local/run_until/block_on.","Treat it as a build-time setting."],"tags":["localset","task","unhandled-panic","panic","configuration"],"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"}