Hmbown/CodeWhale · error
custom_models[ ]. is invalid
Error message
custom_models[{index}].{field} is invalid What it means
`validate_configured_models` enforces structural rules on each entry of the `custom_models` config list: `provider` and `id` must be non-empty, at most 256 chars, and free of whitespace and control characters. The error names the offending entry index and field but deliberately never echoes the invalid value, to avoid leaking untrusted content.
Solutions
- Open the config file and inspect `custom_models[index]` — fix the field named in the message.
- Ensure both `provider` and `id` are non-empty, ≤256 chars, with no spaces or control characters.
- Trim surrounding whitespace from pasted values and re-run the command.
Example fix
// before (config TOML) [[custom_models]] provider = "openai " id = "gpt-4o" // after [[custom_models]] provider = "openai" id = "gpt-4o"
Defensive patterns
Strategy: validation
Validate before calling
fn valid_field(s: &str) -> bool {
!s.is_empty() && s.len() <= 256
&& !s.chars().any(char::is_whitespace)
&& !s.chars().any(char::is_control)
}
// run on each custom_models entry before writing config
assert!(valid_field(&model.provider) && valid_field(&model.id)); Prevention
- Trim pasted provider/id values before saving them to config
- Validate custom_models entries at editor time with the same rules (non-empty, ≤256, no whitespace/control chars)
- Keep model ids to simple identifier characters (letters, digits, dash, dot)
When it happens
Trigger: Deserializing config via `deserialize_configured_models` when a `custom_models[i].provider` or `.id` is empty, longer than 256 characters, or contains spaces/tabs/control characters.
Common situations: Hand-edited config with a trailing space in the model id, a pasted provider name containing a newline, or a copy-paste that left the field blank.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- agent profile provider cannot be empty
- agent profile provider must be a simple provider id
- api_key cannot be empty string
- approval_policy ' ' is not allowed by requirements ( )
- budget document_kind must be
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/c6fca0d1113d96db.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/catalog/configured.rs:73
endpoint_key: "chat".into(),
limit: self.limit.clone(),
cost: self.cost.clone(),
modalities: self.modalities.clone(),
attachment: self.attachment,
reasoning: self.reasoning,
tool_call: self.tool_call,
structured_output: self.structured_output,
source: CatalogSource::ConfigOverride,
..CatalogOffering::default()
}
}
}
pub fn validate_configured_models(models: &[ConfiguredModel]) -> anyhow::Result<()> {
let mut identities = BTreeSet::new();
for (index, model) in models.iter().enumerate() {
// Error messages name fields, never echo untrusted values or URLs.
let invalid = |field| anyhow::anyhow!("custom_models[{index}].{field} is invalid");
for (field, value) in [("provider", &model.provider), ("id", &model.id)] {
if value.is_empty()
|| value.len() > 256
|| value.chars().any(char::is_whitespace)
|| value.chars().any(char::is_control)
{
return Err(invalid(field));
}
}
if model.id.eq_ignore_ascii_case("auto") {
return Err(invalid("id"));
}
let Some((scheme, rest)) = model.base_url.split_once("://") else {
return Err(invalid("base_url"));
};
if !matches!(scheme.to_ascii_lowercase().as_str(), "http" | "https")
|| rest.split('/').next().is_none_or(str::is_empty)
|| model.base_url.contains(['@', '?', '#'])View on GitHub (pinned to 73e0f67d83)