Hmbown/CodeWhale · error

Choose a model for the destination provider before…

Error message

Choose a model for the destination provider before switching from a legacy custom connection; the saved configuration was not changed

What it means

`reconcile_root_model_aliases` (called from `persist_provider_selection`) refuses to reconcile when the outgoing saved connection is a legacy literal `Custom` provider (no persisted id) that differs from the incoming selection. Switching away from such a connection requires a concrete destination model; without one the save is aborted unchanged to avoid destroying the legacy alias state.

Solutions

  1. Select a model for the destination provider before saving the provider switch
  2. If the legacy custom connection is no longer wanted, explicitly remove it first, then set the new provider+model together
Defensive patterns

Strategy: validation

Validate before calling

if outgoing.provider == ApiProvider::Custom
    && outgoing.persisted_id().is_none()
    && outgoing != incoming
    && destination_model.is_none() {
    eprintln!("select a destination model before switching from legacy custom");
}

Type guard

fn is_legacy_custom(c: &Connection) -> bool {
    c.provider == ApiProvider::Custom && c.persisted_id().is_none()
}

Try / catch

match persist_result {
    Err(e) if e.to_string().contains("legacy custom connection") => prompt_for_destination_model_then_retry(),
    other => other?,
}

Prevention

When it happens

Trigger: Calling `persist_provider_selection` while the current connection is a legacy custom connection (`provider == Custom` with no `persisted_id`) and the caller did not supply a model for the destination provider.

Common situations: TUI provider-switch flow where the user picks a new provider but no default model is selected; configs migrated from the old free-form custom-provider format; automated config edits changing the provider without specifying a model.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/135292eac989f841. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/config_persistence.rs:311

    }
    // An empty or control-bearing alias names no saved model. Nothing to
    // relocate, and clearing it loses nothing.
    if value.trim().is_empty() || value.chars().any(char::is_control) {
        unset_document_value(doc, &[ROOT_KEY])?;
        return Ok(());
    }
    // No leaf can hold this value. Keep the only copy of the user's choice
    // rather than discard it for a document the incoming route loads as soon as
    // it saves a model of its own.
    let outgoing = previous
        .active_provider_identity(previous.api_provider())
        .ok();
    if outgoing.as_ref().is_some_and(|outgoing| {
        outgoing != incoming
            && outgoing.provider == ApiProvider::Custom
            && outgoing.persisted_id().is_none()
    }) {
        anyhow::bail!(
            "Choose a model for the destination provider before switching from a legacy custom connection; the saved configuration was not changed"
        );
    }
    let Some(outgoing) = outgoing.as_ref().filter(|outgoing| *outgoing != incoming) else {
        return Ok(());
    };
    let mut scoped = switched;
    scoped.scope_to_provider_identity(outgoing);
    if scoped
        .provider_config_for(outgoing.provider)
        .and_then(|entry| entry.model.as_deref())
        .is_none()
    {
        set_provider_model_document(
            doc,
            outgoing.provider,
            outgoing.persisted_id().unwrap_or(&outgoing.key),
            &value,

View on GitHub (pinned to 73e0f67d83)