Hmbown/CodeWhale · error · anyhow::Error
Invalid default_text_model
Error message
Invalid default_text_model '{model}' for provider '{}': expected auto or a model ID this provider serves{hint}. What it means
`default_text_model` must be `auto` or a model ID the active provider actually serves, resolved by `canonical_model_id_for_provider` (each family's own canonical map; unknown IDs pass through only for pass-through providers or custom base URLs). Since #4829 validation uses the active provider's namespace, not DeepSeek's — and the error lists that provider's known model names as examples.
Solutions
- Set `default_text_model = "auto"` and let the provider choose.
- Use one of the example IDs listed in the error's `(for example: ...)` hint.
- If the ID is correct for your own endpoint, route it through that custom provider/base URL so it passes through unvalidated.
- Check casing and version suffixes of the model ID.
Example fix
# before provider = "deepseek" default_text_model = "gpt-4o" # after provider = "deepseek" default_text_model = "deepseek-chat"
Defensive patterns
Strategy: validation
Validate before calling
fn model_is_acceptable(provider: ApiProvider, model: &str) -> bool {
model.trim().eq_ignore_ascii_case("auto")
|| provider_passes_model_through(provider)
|| canonical_model_id_for_provider(provider, model).is_some()
}
assert!(model_is_acceptable(active_provider, &config.default_text_model)); Type guard
fn is_valid_model_for_provider(provider: ApiProvider, model: &str) -> bool {
model.trim().eq_ignore_ascii_case("auto")
|| canonical_model_id_for_provider(provider, model).is_some()
} Prevention
- When switching providers, switch the model line in the same edit.
- Use `auto` unless you specifically need a pinned model.
- Use the provider's own model listing as the source for IDs; do not cross families.
When it happens
Trigger: `provider = "deepseek"` with `default_text_model = "gpt-4o"`; a typo'd GLM/Kimi/MiniMax model id; mixing a model ID from one family with a different provider.
Common situations: Switching providers without updating the model line; stale IDs after a provider renamed its models; copy-pasting model lists from another provider's docs.
Related errors
- custom provider ' ' must set [providers. ].kind =…
- Invalid provider ' ': expected .
- .context_window must be greater than 0
- .model_context_windows. must be greater than 0
- unknown field ' ' for built-in provider ' ': expected one…
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/80f77d1bd8947b0c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config.rs:4698
// (GLM via Z.ai, Kimi, MiniMax, …) and passes unknown ids through, so
// it rejects only what the provider genuinely cannot serve. Validating
// with the DeepSeek-only `normalize_model_name` bricked every config
// whose provider owns a non-DeepSeek family — including ones our own
// setup wizard writes (`provider = "zai"`, `GLM-5.2`). (#4829)
if let Some(model) = self.default_text_model.as_deref()
&& !model.trim().eq_ignore_ascii_case("auto")
&& !provider_passes_model_through(self.api_provider())
&& !self.active_provider_preserves_custom_base_url_model()
&& 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 default_text_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 0c42157ee5)