linebender/druid · error
should never recompute scale of window that has been dropped
Error message
should never recompute scale of window that has been dropped
What it means
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.
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
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at druid-shell/src/backend/wayland/surfaces/mod.rs:100 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/2b76dc5182e8f486.
Report an issue: GitHub.
Appendix: source
Thrown at druid-shell/src/backend/wayland/surfaces/mod.rs:100
impl CompositorHandle {
pub fn new(c: impl Into<CompositorHandle>) -> Self {
c.into()
}
pub fn direct(c: std::sync::Weak<dyn Compositor>) -> Self {
Self { inner: c }
}
fn create_surface(&self) -> Option<wlc::Main<WlSurface>> {
self.inner.upgrade().map(|c| c.create_surface())
}
/// Recompute the scale to use (the maximum of all the provided outputs).
fn recompute_scale(&self, outputs: &std::collections::HashSet<u32>) -> i32 {
let compositor = match self.inner.upgrade() {
Some(c) => c,
None => panic!("should never recompute scale of window that has been dropped"),
};
tracing::debug!("computing scale using {:?} outputs", outputs.len());
let scale = outputs.iter().fold(0, |scale, id| {
tracing::debug!("recomputing scale using output {:?}", id);
match compositor.output(*id) {
None => {
tracing::warn!(
"we still have a reference to an output that's gone away. The output had id {}",
id,
);
scale
},
Some(output) => scale.max(output.scale as i32),
}
});
match scale {
0 => {View on GitHub (pinned to 0f8b1195e4)