a-b-street/abstreet · error

Can't find widget

Error message

Can't find widget {}

What it means

`Panel::find::<T>` is the infallible variant of maybe_find: it panics when no widget with the given name exists in the panel. Callers (e.g. slider helpers) rely on the widget being present by construction.

Solutions

  1. Guard with `panel.has_widget(name)` before find
  2. Use maybe_find::<T>() and handle the None case instead of find
  3. Ensure the widget is always constructed and added (move creation out of conditionals)
  4. Fix the name typo / keep names in constants

Example fix

// before
let s = panel.find::<Slider>("zoom");
// after
if let Some(s) = panel.maybe_find::<Slider>("zoom") { /* ... */ } else { /* rebuild content */ }
Defensive patterns

Strategy: type-guard

Validate before calling

if panel.has_widget("zoom") {
    let s = panel.find::<Slider>("zoom");
}

Type guard

fn find_slider(panel: &Panel, name: &str) -> Option<&Slider> {
    panel.maybe_find::<Slider>(name)
}

Prevention

When it happens

Trigger: Calling `panel.find::<T>(name)` when the widget was never added, was removed by take/replace/swap_inner_content, or the name is misspelled.

Common situations: Panel content swapped dynamically so an expected widget no longer exists; typo in name; widget created inside a conditional branch that didn't run.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/58870f61c35c64ac. Report an issue: GitHub.

Appendix: source

Thrown at widgetry/src/widgets/panel.rs:491

    }

    pub fn maybe_find_widget(&self, name: &str) -> Option<&Widget> {
        self.top_level.find(name)
    }

    pub fn maybe_find<T: WidgetImpl>(&self, name: &str) -> Option<&T> {
        self.maybe_find_widget(name).map(|w| {
            if let Some(x) = w.widget.downcast_ref::<T>() {
                x
            } else {
                panic!("Found widget {}, but wrong type", name);
            }
        })
    }

    pub fn find<T: WidgetImpl>(&self, name: &str) -> &T {
        self.maybe_find(name)
            .unwrap_or_else(|| panic!("Can't find widget {}", name))
    }

    pub fn find_mut<T: WidgetImpl>(&mut self, name: &str) -> &mut T {
        if let Some(w) = self.top_level.find_mut(name) {
            if let Some(x) = w.widget.downcast_mut::<T>() {
                x
            } else {
                panic!("Found widget {}, but wrong type", name);
            }
        } else {
            panic!("Can't find widget {}", name);
        }
    }

    /// Swap the inner content of a `container` widget with `new_inner_content`.
    pub(crate) fn swap_inner_content(
        &mut self,
        ctx: &EventCtx,

View on GitHub (pinned to 0964f29315)