{"record":{"id":"217fb90fd337ce42","repo":"Hmbown/CodeWhale","slug":"unknown-field-field-key-for-built-in-provider","errorCode":null,"errorMessage":"unknown field '{field_key}' for built-in provider '{provider_id}': expected one of api_key, base_url, model, context_window, mode, auth_mode, insecure_skip_tls_verify, http_headers, path_suffix","messagePattern":"unknown field '(.+?)' for built-in provider '(.+?)': expected one of api_key, base_url, model, context_window, mode, auth_mode, insecure_skip_tls_verify, http_headers, path_suffix","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/lib.rs","lineNumber":2572,"sourceCode":"            .entry(provider_id.to_string())\n            .or_insert_with(|| toml::Value::Table(toml::value::Table::new()));\n        entry.as_table_mut().with_context(|| {\n            format!(\"custom provider '{provider_id}' must be a [providers.{provider_id}] table\")\n        })\n    }\n\n    /// Write one leg of a custom provider table. Named custom providers are\n    /// not in [`ProviderKind::ALL`], so without this path\n    /// `config set providers.<custom>.<field>` fell through to a literal\n    /// top-level extras key and silently never took effect (#5167).\n    fn set_custom_provider_value(\n        &mut self,\n        provider_id: &str,\n        field_key: &str,\n        value: &str,\n    ) -> Result<()> {\n        if is_builtin_provider_config_id(provider_id) {\n            bail!(\n                \"unknown field '{field_key}' for built-in provider '{provider_id}': \\\n                 expected one of api_key, base_url, model, context_window, mode, auth_mode, \\\n                 insecure_skip_tls_verify, http_headers, path_suffix\"\n            );\n        }\n        if field_key == \"kind\" {\n            let compatible =\n                value.trim().to_ascii_lowercase().replace('_', \"-\") == \"openai-compatible\";\n            if !compatible {\n                bail!(\n                    \"custom provider '{provider_id}' must set [providers.{provider_id}].kind = \\\"openai-compatible\\\"\"\n                );\n            }\n            self.custom_provider_table_mut(provider_id)?.insert(\n                \"kind\".to_string(),\n                toml::Value::String(value.trim().to_string()),\n            );\n            return Ok(());","sourceCodeStart":2554,"sourceCodeEnd":2590,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/config/src/lib.rs#L2554-L2590","documentation":"The config crate rejects any field assignment against a built-in provider (a provider whose config id is reserved, via is_builtin_provider_config_id). Built-ins only accept a fixed whitelist of override fields (api_key, base_url, model, context_window, mode, auth_mode, insecure_skip_tls_verify, http_headers, path_suffix); any other key in a [providers.<builtin>] table is refused before parsing so typos fail loudly instead of being silently ignored.","triggerScenarios":"Calling set_provider_config_value / `codewhale config set providers.<builtin-id>.<field> <value>` with a field_key not in the whitelist — typically a typo (apikey, api-key), a custom-provider-only field like kind or vendor, or an invented key.","commonSituations":"Hand-editing config.toml or scripting `config set` for a built-in provider using field names valid for custom providers; copying a custom provider block and renaming the id without removing unsupported fields; version drift where a field existed for built-ins in an older release but was removed.","solutions":["Use one of the accepted fields: api_key, base_url, model, context_window, mode, auth_mode, insecure_skip_tls_verify, http_headers, path_suffix","Fix the field spelling to match the whitelist exactly (snake_case)","If you need arbitrary fields (e.g. kind, vendor), define a custom provider id instead of configuring the built-in","Check the docs for the current field list — the whitelist is version-specific"],"exampleFix":"// before\ncodewhale config set providers.openai.kind openai-compatible\n// after\ncodewhale config set providers.openai.base_url https://api.openai.example/v1","handlingStrategy":"validation","validationCode":"const BUILTIN_FIELDS: [&str; 9] = [\"api_key\",\"base_url\",\"model\",\"context_window\",\"mode\",\"auth_mode\",\"insecure_skip_tls_verify\",\"http_headers\",\"path_suffix\"];\nif is_builtin_provider_config_id(provider_id) && !BUILTIN_FIELDS.contains(&field_key) {\n    return Err(format!(\"{field_key} not allowed for built-in provider {provider_id}\"));\n}","typeGuard":"fn is_builtin_field(field: &str) -> bool {\n    matches!(field, \"api_key\"|\"base_url\"|\"model\"|\"context_window\"|\"mode\"|\"auth_mode\"|\"insecure_skip_tls_verify\"|\"http_headers\"|\"path_suffix\")\n}","tryCatchPattern":"match config.set_provider_config_value(provider_id, field_key, value) {\n    Err(e) if e.to_string().contains(\"unknown field\") => eprintln!(\"bad field {field_key}; use api_key/base_url/model/...\"),\n    other => other?,\n}","preventionTips":["Keep the field whitelist in a shared constant next to your setters","Validate provider config tables at load time with a schema","Distinguish built-in vs custom provider ids in your config UI","Test config writes for both provider classes"],"tags":["config","provider","validation"],"backgroundTag":"invalid-config-value","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"}