{"record":{"id":"05026a7d166ed793","repo":"Hmbown/CodeWhale","slug":"invalid-provider-provider-expected","errorCode":null,"errorMessage":"Invalid provider '{provider}': expected {}.","messagePattern":"Invalid provider '(.+?)': expected (.+?)\\.","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":4361,"sourceCode":"        };\n        tracing::warn!(\n            \"Top-level `base_url = \\\"{root_base}\\\"` is ignored for the {provider:?} provider. \\\n             Move it under `[{table}]` (e.g. `[{table}]\\\\nbase_url = \\\"...\\\"`) \\\n             or set the corresponding `*_BASE_URL` env var. (#1308)\"\n        );\n    }\n\n    /// Validate that critical config fields are present.\n    pub fn validate(&self) -> Result<()> {\n        if let Some(provider) = self.provider.as_deref()\n            && ApiProvider::parse(provider).is_none()\n            && self\n                .providers\n                .as_ref()\n                .and_then(|providers| providers.custom_provider_config(provider))\n                .is_none()\n        {\n            anyhow::bail!(\n                \"Invalid provider '{provider}': expected {}.\",\n                ApiProvider::names_hint()\n            );\n        }\n        let active_provider = self.api_provider();\n        match validate_kimi_code_api_model_id(\n            active_provider,\n            &self.deepseek_base_url(),\n            &self.default_model(),\n        ) {\n            Err(error) if error == KIMI_CODE_CLAUDE_ALIAS_GUIDANCE => {\n                return Err(SafeConfigDiagnostic::KimiCodeClaudeAlias.into());\n            }\n            result => result.map_err(anyhow::Error::msg)?,\n        }\n        if let Some(ref key) = self.api_key\n            && key.trim().is_empty()\n        {","sourceCodeStart":4343,"sourceCodeEnd":4379,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/config.rs#L4343-L4379","documentation":"Config validation (crates/tui/src/config.rs:4361) rejects the provider string when ApiProvider::parse cannot recognize it AND no matching custom entry exists under [providers.<name>]. The message embeds the full accepted list from ApiProvider::names_hint() (deepseek, zai, kimi, minimax, moonshot, openai-compatible ids like ollama/vllm/sglang/together, anthropic, google, xai, mistral, ..., custom).","triggerScenarios":"A typo or wrong-case id (ZAI vs zai); using a vendor name that is not a registered id; referencing a custom provider before defining its [providers.<name>] section; profile switching to a provider only defined in another profile.","commonSituations":"Upgrade adding/renaming provider ids; copying a provider line from another tool's config; defining the custom section under a different key than the one referenced.","solutions":["Fix the id to an exact name from the error's expected list (ids are case-sensitive)","Or define the provider first: a [providers.<name>] section with api_base/model, then set provider = \"<name>\"","Check that the custom provider section lives in the same file/profile being loaded","Rerun and confirm validation passes"],"exampleFix":"# config.toml - before\nprovider = \"ZAI\"\n\n# config.toml - after\nprovider = \"zai\"\n# or, for a custom endpoint:\n# [providers.myhost]\n# api_base = \"http://localhost:8000/v1\"\n# provider = \"myhost\"\n","handlingStrategy":"validation","validationCode":"let ok = ApiProvider::parse(provider).is_some()\n    || custom_providers.contains_key(provider);\nassert!(ok, \"unknown provider {provider}\");","typeGuard":"fn provider_is_known(provider: &str, custom: &HashMap<String, ProviderCfg>) -> bool {\n    ApiProvider::parse(provider).is_some() || custom.contains_key(provider)\n}","tryCatchPattern":"// Suggest the nearest known id on failure\nif !provider_is_known(p, &custom) {\n    return Err(anyhow!(\"unknown provider {p}; did you mean '{}'?\", closest_name(p)));\n}","preventionTips":["Provider ids are case-sensitive - copy them from names_hint() output","Define the [providers.<name>] section before referencing it","Re-check the accepted list after upgrades; ids get added and renamed"],"tags":["config","provider","validation","typo"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}