{"record":{"id":"2b76dc5182e8f486","repo":"linebender/druid","slug":"should-never-recompute-scale-of-window-that-has-be","errorCode":null,"errorMessage":"should never recompute scale of window that has been dropped","messagePattern":"should never recompute scale of window that has been dropped","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"druid-shell/src/backend/wayland/surfaces/mod.rs","lineNumber":100,"sourceCode":"\nimpl CompositorHandle {\n    pub fn new(c: impl Into<CompositorHandle>) -> Self {\n        c.into()\n    }\n\n    pub fn direct(c: std::sync::Weak<dyn Compositor>) -> Self {\n        Self { inner: c }\n    }\n\n    fn create_surface(&self) -> Option<wlc::Main<WlSurface>> {\n        self.inner.upgrade().map(|c| c.create_surface())\n    }\n\n    /// Recompute the scale to use (the maximum of all the provided outputs).\n    fn recompute_scale(&self, outputs: &std::collections::HashSet<u32>) -> i32 {\n        let compositor = match self.inner.upgrade() {\n            Some(c) => c,\n            None => panic!(\"should never recompute scale of window that has been dropped\"),\n        };\n        tracing::debug!(\"computing scale using {:?} outputs\", outputs.len());\n        let scale = outputs.iter().fold(0, |scale, id| {\n            tracing::debug!(\"recomputing scale using output {:?}\", id);\n            match compositor.output(*id) {\n                None => {\n                    tracing::warn!(\n                        \"we still have a reference to an output that's gone away. The output had id {}\",\n                        id,\n                    );\n                    scale\n                },\n                Some(output) => scale.max(output.scale as i32),\n            }\n        });\n\n        match scale {\n            0 => {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/linebender/druid/blob/0f8b1195e4e073f9597f2865299c3d18f8e4005f/druid-shell/src/backend/wayland/surfaces/mod.rs#L82-L118","documentation":"Generic guard in CompositorHandle::recompute_scale: the Weak<dyn Compositor> held by the handle has been dropped, so the scale cannot be recomputed. It fires when output configuration changes (outputs added/removed) arrive for a window whose compositor backend has already been dropped, i.e. a use-after-drop of the window's wayland resources.","triggerScenarios":"Thrown at druid-shell/src/backend/wayland/surfaces/mod.rs:100 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure the CompositorHandle is dropped together with (or before) the compositor it points to, so no events are delivered to a dead handle","Check Weak::upgrade success before handling output/scale events and skip processing when the compositor is gone","Keep a strong reference alive as long as the surface can receive wayland events"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"0f8b1195e4e073f9597f2865299c3d18f8e4005f","analyzedAt":"2026-09-10T14:27:34.582Z","contentChangedAt":"2026-09-10T14:27:34.582Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}