Hmbown/CodeWhale · error

Invalid configured model

Error message

Invalid configured model '{model}' for provider '{}': expected auto or a model ID this provider serves{hint}.

What it means

The config validator checks the configured model against the model ID namespace of the *active* provider via `model_completion_names_for_provider(provider)`. Only `auto` or a model ID that provider actually serves is accepted; anything else is rejected with a hint listing example valid IDs.

Solutions

  1. Set `model = "auto"` in the config to let the provider resolver pick the model.
  2. Pick a model ID from the hint list in the error message (examples come from `model_completion_names_for_provider` for your active provider).
  3. If you switched providers, also update `api_provider` so the model is validated against the intended namespace.
  4. Verify the model ID is one the provider currently serves (provider may have deprecated it).

Example fix

// before (config.toml)
model = "gpt-4o"   # active provider is openrouter

// after
model = "auto"
# or
model = "openai/gpt-4o"
Defensive patterns

Strategy: validation

Validate before calling

use codewhale::tui::config::model_completion_names_for_provider;
let known = model_completion_names_for_provider(provider);
let ok = model == "auto" || known.iter().any(|m| *m == model);
assert!(ok, "model '{model}' not served by {}; valid: {known:?}", provider.as_str());

Prevention

When it happens

Trigger: `Config::validate` runs and the configured `model` value is neither the literal `auto` nor one of the completion names returned by `model_completion_names_for_provider` for the currently selected provider.

Common situations: Switching providers (e.g. from DeepSeek to OpenRouter) but keeping the old provider's model ID; typos in the model string; using a model name that the provider retired or never served; copying a model ID from another tool's config.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/config.rs:5155

            && !self.active_provider_preserves_custom_base_url_model()
            && crate::provider_lake::configured_model_for_route(
                self,
                active_provider,
                &self.provider_identity_for(active_provider),
                &self.base_url_for_route(active_provider),
                model,
            )
            .is_none()
            && canonical_model_id_for_provider(self.api_provider(), model).is_none()
        {
            let provider = self.api_provider();
            let known = model_completion_names_for_provider(provider);
            let hint = if known.is_empty() {
                String::new()
            } else {
                format!(" (for example: {})", known.join(", "))
            };
            anyhow::bail!(
                "Invalid configured model '{model}' for provider '{}': expected auto or a model ID this provider serves{hint}.",
                provider.as_str()
            );
        }
        if let Some(policy) = self.approval_policy.as_deref() {
            let normalized = policy.trim().to_ascii_lowercase();
            if !matches!(
                normalized.as_str(),
                "on-request" | "untrusted" | "never" | "auto" | "suggest"
            ) {
                anyhow::bail!(
                    "Invalid approval_policy '{policy}': expected on-request, untrusted, never, auto, or suggest."
                );
            }
        }
        if let Some(v) = self.verbosity.as_deref() {
            let normalized = v.trim().to_ascii_lowercase();
            if !matches!(normalized.as_str(), "normal" | "concise") {

View on GitHub (pinned to 73e0f67d83)