{"record":{"id":"57272d307c48b2fa","repo":"iced-rs/iced","slug":"write-last-palette","errorCode":null,"errorMessage":"Write last palette","messagePattern":"Write last palette","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"debug/src/lib.rs","lineNumber":175,"sourceCode":"    pub fn quit() -> bool {\n        if BEACON.is_connected() {\n            BEACON.quit();\n\n            true\n        } else {\n            false\n        }\n    }\n\n    pub fn theme_changed(f: impl FnOnce() -> Option<palette::Seed>) {\n        let Some(palette) = f() else {\n            return;\n        };\n\n        if METADATA.read().expect(\"Read last palette\").theme.as_ref() != Some(&palette) {\n            log(client::Event::ThemeChanged(palette));\n\n            METADATA.write().expect(\"Write last palette\").theme = Some(palette);\n        }\n    }\n\n    pub fn tasks_spawned(amount: usize) {\n        log(client::Event::CommandsSpawned(amount));\n    }\n\n    pub fn subscriptions_tracked(amount: usize) {\n        log(client::Event::SubscriptionsTracked(amount));\n    }\n\n    pub fn layers_rendered(amount: impl FnOnce() -> usize) {\n        log(client::Event::LayersRendered(amount()));\n    }\n\n    pub fn boot() -> Span {\n        span(span::Stage::Boot)\n    }","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/iced-rs/iced/blob/2cffa99b395d84fe469b44dccb56bbacd2f1a157/debug/src/lib.rs#L157-L193","documentation":"After deciding the palette actually changed, `debug::theme_changed` records it with `METADATA.write().expect(\"Write last palette\")`. The expect fires only when the RwLock is poisoned — an earlier panic held a guard — since the write itself cannot fail otherwise.","triggerScenarios":"A theme change in a debug-instrumented app after the METADATA lock was poisoned by an earlier panic under one of its guards (init, BEACON LazyLock, or a prior theme_changed call).","commonSituations":"Debug builds with live theme switching after a swallowed panic; multiple threads logging theme events while a crash reporter masks the original failure.","solutions":["Fix the root-cause panic that poisoned METADATA first","Recover instead of panicking: `write().unwrap_or_else(PoisonError::into_inner)`","Initialize debug state once at startup so later writes are single-threaded until the runtime spreads","Disable the debug feature where it is not needed"],"exampleFix":"// before\nMETADATA.write().expect(\"Write last palette\").theme = Some(palette);\n// after\nMETADATA\n    .write()\n    .unwrap_or_else(std::sync::PoisonError::into_inner)\n    .theme = Some(palette);","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let _ = std::panic::catch_unwind(|| debug::theme_changed(|| current_palette()));","preventionTips":["Treat the METADATA write panic as evidence of an earlier poisoning panic elsewhere","Do not swallow panics with catch_unwind and keep the app running — poisoning spreads to later lock users","Gate theme telemetry behind the debug feature only in development builds","Maintainers: unwrap_or_else(PoisonError::into_inner) makes palette tracking survive poisoning"],"tags":["rust","iced","debug","theme","rwlock","lock-poisoning","panic"],"backgroundTag":"lock-poisoned","analyzedSha":"2cffa99b395d84fe469b44dccb56bbacd2f1a157","analyzedAt":"2026-08-16T19:41:49.083Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}