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
- Guard with `panel.has_widget(name)` before find
- Use maybe_find::<T>() and handle the None case instead of find
- Ensure the widget is always constructed and added (move creation out of conditionals)
- 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
- Prefer maybe_find over find when existence isn't guaranteed
- Guard with has_widget before find
- Keep panel-content construction unconditional for expected widgets
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
- Can't scroll_to_member of unknown
- Panel doesn't have
- Two buttons in one Panel both use action
- Can't take( ), it's a top-level widget
- Found widget , but wrong type
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)