Hmbown/CodeWhale · error
unknown field ' ' for built-in provider ' ': expected one…
Error message
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 What it means
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.
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
Example fix
// before codewhale config set providers.openai.kind openai-compatible // after codewhale config set providers.openai.base_url https://api.openai.example/v1
Defensive patterns
Strategy: validation
Validate before calling
const BUILTIN_FIELDS: [&str; 9] = ["api_key","base_url","model","context_window","mode","auth_mode","insecure_skip_tls_verify","http_headers","path_suffix"];
if is_builtin_provider_config_id(provider_id) && !BUILTIN_FIELDS.contains(&field_key) {
return Err(format!("{field_key} not allowed for built-in provider {provider_id}"));
} Type guard
fn is_builtin_field(field: &str) -> bool {
matches!(field, "api_key"|"base_url"|"model"|"context_window"|"mode"|"auth_mode"|"insecure_skip_tls_verify"|"http_headers"|"path_suffix")
} Try / catch
match config.set_provider_config_value(provider_id, field_key, value) {
Err(e) if e.to_string().contains("unknown field") => eprintln!("bad field {field_key}; use api_key/base_url/model/..."),
other => other?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- custom provider ' ' must set [providers. ].kind =…
- Invalid default_text_model
- Invalid provider ' ': expected .
- .context_window must be greater than 0
- .model_context_windows. must be greater than 0
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/217fb90fd337ce42.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/lib.rs:2572
.entry(provider_id.to_string())
.or_insert_with(|| toml::Value::Table(toml::value::Table::new()));
entry.as_table_mut().with_context(|| {
format!("custom provider '{provider_id}' must be a [providers.{provider_id}] table")
})
}
/// Write one leg of a custom provider table. Named custom providers are
/// not in [`ProviderKind::ALL`], so without this path
/// `config set providers.<custom>.<field>` fell through to a literal
/// top-level extras key and silently never took effect (#5167).
fn set_custom_provider_value(
&mut self,
provider_id: &str,
field_key: &str,
value: &str,
) -> Result<()> {
if is_builtin_provider_config_id(provider_id) {
bail!(
"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"
);
}
if field_key == "kind" {
let compatible =
value.trim().to_ascii_lowercase().replace('_', "-") == "openai-compatible";
if !compatible {
bail!(
"custom provider '{provider_id}' must set [providers.{provider_id}].kind = \"openai-compatible\""
);
}
self.custom_provider_table_mut(provider_id)?.insert(
"kind".to_string(),
toml::Value::String(value.trim().to_string()),
);
return Ok(());View on GitHub (pinned to 73e0f67d83)