a-b-street/abstreet · error
Dropdown has default_value , but none of the choices match…
Error message
Dropdown {} has default_value {:?}, but none of the choices match that What it means
Dropdown::new validates that the requested default_value matches one of the provided choices' data; if no choice's data equals default_value it panics. This is a constructor-time invariant so the dropdown can compute its initial selected index.
Solutions
- Ensure default_value exactly matches one of the choices' data (same value, same PartialEq semantics).
- Derive default_value from the choices themselves, e.g. choices[0].data.clone().
- If the persisted default may be stale, clamp it to the available choices before constructing.
- Consider Dropdown::maybe_new-style tolerant construction if your codebase offers it.
Example fix
// before
Dropdown::new(widget_ctx, "mode", vec![Choice::new("fast"), Choice::new("slow")], saved_mode)
// after
let default = choices.iter().map(|c| c.data.clone()).find(|d| *d == saved_mode).unwrap_or_else(|| choices[0].data.clone());
Dropdown::new(widget_ctx, "mode", choices, default) Defensive patterns
Strategy: validation
Validate before calling
assert!(
choices.iter().any(|c| c.data == default_value),
"default {:?} not among choices {:?}",
default_value,
choices.iter().map(|c| &c.data).collect::<Vec<_>>()
); Try / catch
let default = if choices.iter().any(|c| c.data == saved) { saved } else { choices[0].data.clone() };
Dropdown::new(ctx, "label", choices, default) Prevention
- Always derive default_value from the choices list, not external constants
- Clamp persisted/old defaults to available choices before constructing
- Re-check equality semantics after refactoring the choice data type
When it happens
Trigger: Calling Dropdown::new (or the widget builder) with choices whose .data values never equal the default_value passed in — including type/equality mismatches (e.g. comparing enum variants not in the list, mismatched IDs after data changes).
Common situations: Choices generated dynamically from data while default_value is hardcoded; a refactor changing the data payload so equality no longer holds; default derived from persisted settings that no longer exist in the choice list.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- CityName::new( , ) has a country code that isn't two letters
- Can't delete ; it's not in the World
- Can't delete mid-drag
- Failed to load svg from bytes. cache_key
- to_geom called on a widget tree that has something…
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/fdc2392c500e17e6.
Report an issue: GitHub.
Appendix: source
Thrown at widgetry/src/widgets/dropdown.rs:31
label: String,
is_persisten_split: bool,
choices: Vec<Choice<T>>,
}
impl<T: 'static + PartialEq + Clone + std::fmt::Debug> Dropdown<T> {
pub fn new(
ctx: &EventCtx,
label: &str,
default_value: T,
choices: Vec<Choice<T>>,
// TODO Ideally builder style
is_persisten_split: bool,
) -> Dropdown<T> {
let current_idx = if let Some(idx) = choices.iter().position(|c| c.data == default_value) {
idx
} else {
panic!(
"Dropdown {} has default_value {:?}, but none of the choices match that",
label, default_value
);
};
Dropdown {
current_idx,
btn: make_btn(ctx, &choices[current_idx].label, label, is_persisten_split),
menu: None,
label: label.to_string(),
is_persisten_split,
choices,
}
}
}
impl<T: 'static + PartialEq + Clone> Dropdown<T> {
pub fn current_value(&self) -> T {View on GitHub (pinned to 0964f29315)