{"record":{"id":"024ca3af51bef3af","repo":"Hmbown/CodeWhale","slug":"unknown-field-field-key-for-custom-provider","errorCode":null,"errorMessage":"unknown field '{field_key}' for custom provider '{provider_id}': expected one of api_key, base_url, model, context_window, mode, wire, auth_mode, insecure_skip_tls_verify, http_headers, path_suffix, kind","messagePattern":"unknown field '(.+?)' for custom provider '(.+?)': expected one of api_key, base_url, model, context_window, mode, wire, auth_mode, insecure_skip_tls_verify, http_headers, path_suffix, kind","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/config/src/lib.rs","lineNumber":2692,"sourceCode":"                 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(());\n        }\n        let Some(field) = ProviderConfigField::parse(field_key) else {\n            bail!(\n                \"unknown field '{field_key}' for custom provider '{provider_id}': \\\n                 expected one of {CUSTOM_PROVIDER_FIELD_HINT}\"\n            );\n        };\n        let toml_value = match field {\n            ProviderConfigField::ApiKey\n            | ProviderConfigField::BaseUrl\n            | ProviderConfigField::Model\n            | ProviderConfigField::Mode\n            | ProviderConfigField::Wire\n            | ProviderConfigField::AuthMode\n            | ProviderConfigField::PathSuffix => toml::Value::String(value.to_string()),\n            ProviderConfigField::ContextWindow => {\n                toml::Value::Integer(i64::from(parse_context_window(value)?))\n            }\n            ProviderConfigField::InsecureSkipTlsVerify => toml::Value::Boolean(parse_bool(value)?),\n            ProviderConfigField::HttpHeaders => toml::Value::Table(\n                parse_http_headers(value)?","sourceCodeStart":2674,"sourceCodeEnd":2710,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/config/src/lib.rs#L2674-L2710","documentation":"set_custom_provider_value (crates/config/src/lib.rs:2692) rejects `config set providers.<custom>.<field>` when <field> is neither `kind` nor parseable by ProviderConfigField::parse. Custom providers accept a slightly wider set than built-ins (adds wire and kind). The bail exists so a typo fails loudly instead of silently writing a dead extras key (#5167).","triggerScenarios":"`config set providers.<id>.bas_url ...` (typo), or a field like `temperature` that is not part of the provider table schema at all.","commonSituations":"Typos, assuming arbitrary model options (temperature, max_tokens) are provider-table fields, migrating a config from another tool with different key names.","solutions":["Fix the field name to one of: api_key, base_url, model, context_window, mode, wire, auth_mode, insecure_skip_tls_verify, http_headers, path_suffix, kind","Set per-request model options in the request/agent config, not the provider table","Tab-complete or list provider fields before writing in scripts"],"exampleFix":"# before\ncodewhale config set providers.local bas_url http://localhost:8080/v1\n# -> unknown field 'bas_url' for custom provider 'local'\n\n# after\ncodewhale config set providers.local base_url http://localhost:8080/v1","handlingStrategy":"validation","validationCode":"const CUSTOM_FIELDS: &[&str] = &[\"api_key\",\"base_url\",\"model\",\"context_window\",\"mode\",\"wire\",\"auth_mode\",\"insecure_skip_tls_verify\",\"http_headers\",\"path_suffix\",\"kind\"];\nassert!(CUSTOM_FIELDS.contains(&field_key)); // before config set on a custom id","typeGuard":"fn is_custom_provider_field(field: &str) -> bool {\n    [\"api_key\",\"base_url\",\"model\",\"context_window\",\"mode\",\"wire\",\"auth_mode\",\"insecure_skip_tls_verify\",\"http_headers\",\"path_suffix\",\"kind\"].contains(&field)\n}","tryCatchPattern":null,"preventionTips":["Use tab-completion or field lists when scripting config set","Remember model options like temperature do not belong in the provider table","Read back the provider table after scripted edits to confirm keys took effect"],"tags":["rust","config","cli","validation","typo"],"backgroundTag":"unknown-config-field","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}