{"record":{"id":"e2634c8a5dd9ff80","repo":"Hmbown/CodeWhale","slug":"custom-provider-provider-id-must-set-provider","errorCode":null,"errorMessage":"custom provider '{provider_id}' must set [providers.{provider_id}].kind = \"openai-compatible\"","messagePattern":"custom provider '(.+?)' must set \\[providers\\.(.+?)\\]\\.kind = \"openai-compatible\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/lib.rs","lineNumber":2530,"sourceCode":"            .extras\n            .get(provider_id)\n            .and_then(toml::Value::as_table)\n            .with_context(|| {\n                format!(\n                    \"custom provider '{provider_id}' requires a matching [providers.{provider_id}] table\"\n                )\n            })?;\n        let compatible = table\n            .get(\"kind\")\n            .and_then(toml::Value::as_str)\n            .is_some_and(|kind| {\n                kind.trim()\n                    .to_ascii_lowercase()\n                    .replace('_', \"-\")\n                    .eq(\"openai-compatible\")\n            });\n        if !compatible {\n            bail!(\n                \"custom provider '{provider_id}' must set [providers.{provider_id}].kind = \\\"openai-compatible\\\"\"\n            );\n        }\n        Ok(table)\n    }\n\n    fn named_custom_provider_config(&self) -> Option<ProviderConfigToml> {\n        let provider_id = self.named_custom_provider_id()?;\n        self.named_custom_provider_table(provider_id).ok()?;\n        self.providers\n            .extras\n            .get(provider_id)\n            .cloned()?\n            .try_into()\n            .ok()\n    }\n\n    /// Mutable access to a custom provider's `[providers.<id>]` table,","sourceCodeStart":2512,"sourceCodeEnd":2548,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/config/src/lib.rs#L2512-L2548","documentation":"Thrown when validating a custom provider table: every entry under `[providers.<id>]` must declare `kind = \"openai-compatible\"` (case-insensitive; underscores allowed for hyphens). A custom provider without this exact kind marker cannot be constructed as a table, because the library only knows how to build OpenAI-compatible custom providers.","triggerScenarios":"Defining a custom provider in config.toml whose `[providers.<provider_id>]` table is missing the `kind` key, or sets it to something other than \"openai-compatible\" (e.g. \"anthropic\", \"ollama\", or an empty value) — checked via the table validation reached from config loading/custom-provider construction.","commonSituations":"User adds a custom provider section and forgets `kind`; copies a provider block from docs for a native provider and pastes it as a custom entry; typo like `kind = \"openai_compatible\"` with the wrong separator is fine (normalized), but `kind = \"custom\"` fails.","solutions":["Add `kind = \"openai-compatible\"` inside the `[providers.<provider_id>]` table.","Correct the `kind` value to exactly \"openai-compatible\" (case/underscore-insensitive).","If the provider needs a non-OpenAI protocol, do not register it as a custom provider; use a built-in provider kind instead."],"exampleFix":"// before\n[providers.my_llm]\nbase_url = \"http://localhost:8080/v1\"\n// after\n[providers.my_llm]\nkind = \"openai-compatible\"\nbase_url = \"http://localhost:8080/v1\"","handlingStrategy":"validation","validationCode":"fn custom_provider_table_valid(t: &toml::Table) -> bool {\n    t.get(\"kind\")\n        .and_then(|k| k.as_str())\n        .map(|k| k.trim().to_ascii_lowercase().replace('_', \"-\") == \"openai-compatible\")\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match load_config() {\n    Err(e) if e.to_string().contains(\"openai-compatible\") => {\n        eprintln!(\"{e}\");\n        // add kind = \"openai-compatible\" to the offending [providers.<id>] table\n    }\n    other => other,\n}","preventionTips":["Always include `kind = \"openai-compatible\"` in every custom provider table.","Use a config template/snippet for custom providers instead of writing tables from scratch.","Validate config.toml after hand-editing custom provider sections."],"tags":["config","validation","provider","custom-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-23T08:17:48.524Z"}