a-b-street/abstreet · error
Two buttons in one Panel both use action
Error message
Two buttons in one Panel both use action {} What it means
Panel builds a map from click action strings to handlers; if two enabled Buttons in the same Panel share the same action string, event routing would be ambiguous, so the library panics. Action strings must be unique within a Panel.
Solutions
- Rename one button's action to a unique string (e.g. prefix with the section name)
- If both buttons should do the same thing, keep one and reuse the same widget instead of duplicating
- Only one of the buttons may be enabled at a time — the check skips disabled buttons
- Generate action strings programmatically to guarantee uniqueness
Example fix
// before
btn1 = Button::text("Save", "save");
btn2 = Button::text("Save", "save");
// after
btn2 = Button::text("Save", "save_final"); Defensive patterns
Strategy: validation
Validate before calling
let mut seen = std::collections::HashSet::new();
for action in [btn1.action.clone(), btn2.action.clone()] {
assert!(seen.insert(action), "duplicate action {}", action);
} Prevention
- Keep action strings in an enum mapped to unique strings
- Never duplicate button constructors; reuse one widget when behavior is identical
- Remember the check only counts enabled buttons
When it happens
Trigger: Creating two Button widgets with the same `.action(...)` string (e.g. reusing "back" or a constant) and both being enabled when the Panel lays out and calls get_all_click_actions.
Common situations: Copy-pasting button construction without renaming the action; a loop that adds several buttons but reuses one action constant; two containers each adding a similarly-named button.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Can't take( ), it's a top-level widget
- Can't scroll_to_member of unknown
- Found widget , but wrong type
- Can't find widget
- Panel doesn't have
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/75cb957ceaa9e127.
Report an issue: GitHub.
Appendix: source
Thrown at widgetry/src/widgets/mod.rs:717
nodes,
x + dx,
y + dy,
scroll_offset,
ctx,
recompute_layout,
defer_draw,
);
}
} else {
self.widget.set_pos(top_left);
}
}
fn get_all_click_actions(&self, actions: &mut HashSet<String>) {
if let Some(btn) = self.widget.downcast_ref::<Button>() {
if btn.is_enabled() {
if actions.contains(&btn.action) {
panic!("Two buttons in one Panel both use action {}", btn.action);
}
actions.insert(btn.action.clone());
}
} else if let Some(container) = self.widget.downcast_ref::<Container>() {
for w in &container.members {
w.get_all_click_actions(actions);
}
}
}
fn currently_hovering(&self) -> Option<&String> {
if let Some(btn) = self.widget.downcast_ref::<Button>() {
if btn.hovering {
return Some(&btn.action);
}
} else if let Some(checkbox) = self.widget.downcast_ref::<Toggle>() {
if checkbox.btn.hovering {
return Some(&checkbox.btn.action);View on GitHub (pinned to 0964f29315)