{"record":{"id":"135292eac989f841","repo":"Hmbown/CodeWhale","slug":"choose-a-model-for-the-destination-provider-before-switching","errorCode":null,"errorMessage":"Choose a model for the destination provider before switching from a legacy custom connection; the saved configuration was not changed","messagePattern":"Choose a model for the destination provider before switching from a legacy custom connection; the saved configuration was not changed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/config_persistence.rs","lineNumber":311,"sourceCode":"    }\n    // An empty or control-bearing alias names no saved model. Nothing to\n    // relocate, and clearing it loses nothing.\n    if value.trim().is_empty() || value.chars().any(char::is_control) {\n        unset_document_value(doc, &[ROOT_KEY])?;\n        return Ok(());\n    }\n    // No leaf can hold this value. Keep the only copy of the user's choice\n    // rather than discard it for a document the incoming route loads as soon as\n    // it saves a model of its own.\n    let outgoing = previous\n        .active_provider_identity(previous.api_provider())\n        .ok();\n    if outgoing.as_ref().is_some_and(|outgoing| {\n        outgoing != incoming\n            && outgoing.provider == ApiProvider::Custom\n            && outgoing.persisted_id().is_none()\n    }) {\n        anyhow::bail!(\n            \"Choose a model for the destination provider before switching from a legacy custom connection; the saved configuration was not changed\"\n        );\n    }\n    let Some(outgoing) = outgoing.as_ref().filter(|outgoing| *outgoing != incoming) else {\n        return Ok(());\n    };\n    let mut scoped = switched;\n    scoped.scope_to_provider_identity(outgoing);\n    if scoped\n        .provider_config_for(outgoing.provider)\n        .and_then(|entry| entry.model.as_deref())\n        .is_none()\n    {\n        set_provider_model_document(\n            doc,\n            outgoing.provider,\n            outgoing.persisted_id().unwrap_or(&outgoing.key),\n            &value,","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/config_persistence.rs#L293-L329","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Select a model for the destination provider before saving the provider switch","If the legacy custom connection is no longer wanted, explicitly remove it first, then set the new provider+model together"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if outgoing.provider == ApiProvider::Custom\n    && outgoing.persisted_id().is_none()\n    && outgoing != incoming\n    && destination_model.is_none() {\n    eprintln!(\"select a destination model before switching from legacy custom\");\n}","typeGuard":"fn is_legacy_custom(c: &Connection) -> bool {\n    c.provider == ApiProvider::Custom && c.persisted_id().is_none()\n}","tryCatchPattern":"match persist_result {\n    Err(e) if e.to_string().contains(\"legacy custom connection\") => prompt_for_destination_model_then_retry(),\n    other => other?,\n}","preventionTips":["Always resolve a concrete model for the destination before a provider switch","Migrate legacy free-form custom connections to persisted ids","Surface model selection in the UI whenever the current connection is legacy custom"],"tags":["config","model-selection","migration","provider"],"backgroundTag":"missing-required-config-field","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}