a-b-street/abstreet · error

Panel doesn't have

Error message

Panel doesn't have {}

What it means

Panel::replace swaps the widget with the given ID for a new one. This fires when top_level.find_mut(id) returns None — the panel contains no widget with that ID, so the caller is trying to replace a widget that was never added or was already removed/taken. It is a UI programming-error guard.

Solutions

  1. Check `panel.has_widget(id)` before replace; add the widget instead if missing
  2. Ensure the original widget was named with `.named(id)` so find_mut can locate it
  3. Don't take() a widget you later intend to replace — replace returns the old one if needed via other APIs
  4. Verify content-rebuild logic always inserts the widget being replaced

Example fix

// before
panel.replace(ctx, "row3", new_row); // panics if absent
// after
if panel.has_widget("row3") {
    panel.replace(ctx, "row3", new_row);
} else {
    panel.add_widget(new_row.named("row3"));
}
Defensive patterns

Strategy: validation

Validate before calling

if panel.has_widget("row3") {
    panel.replace(ctx, "row3", new_row.named("row3"));
}

Prevention

When it happens

Trigger: Calling `panel.replace(ctx, "row3", new_widget)` where "row3" was never added, already removed via take, or its name changed after swap_inner_content.

Common situations: Rebuilding panel contents dynamically and replacing a row that a conditional branch skipped; typos in id; replacing after take consumed the original.

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/48cc795f73ff74e0. Report an issue: GitHub.

Appendix: source

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

pub fn replace(&mut self, ctx: &mut EventCtx, id: &str, mut new: Widget) {
    if let Some(ref new_id) = new.id {
        assert_eq!(id, new_id);
    }
    new = new.named(id);
    let old = self
        .top_level
        .find_mut(id)
        .unwrap_or_else(|| panic!("Panel doesn't have {}", id));
    new.layout.style = old.layout.style;
    *old = new;
    self.recompute_layout(ctx, true);
}

View on GitHub (pinned to 0964f29315)