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

  1. Ensure default_value exactly matches one of the choices' data (same value, same PartialEq semantics).
  2. Derive default_value from the choices themselves, e.g. choices[0].data.clone().
  3. If the persisted default may be stale, clamp it to the available choices before constructing.
  4. 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

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


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)