Hmbown/CodeWhale · error · anyhow::Error
Runtime provider identity is invalid
Error message
Runtime provider identity is invalid
What it means
The resolved provider identity used to build the Runtime model-catalog URL is validated to contain only lowercase ASCII letters, digits, and hyphens. If the provider name (taken from the current provider iteration) contains other characters, the app-server rejects it before issuing a request, since it would produce an invalid/unintended provider route.
Solutions
- Rename the provider in the Runtime configuration to kebab-case (lowercase letters, digits, hyphens only).
- Check where the provider id originates (config file vs. catalog listing) and correct the source value.
- Verify the Runtime version's expected provider naming scheme.
Example fix
// before (provider config) provider = "OpenAI_Main" // after provider = "openai-main"
Defensive patterns
Strategy: validation
Validate before calling
// validate provider ids are kebab-case before use
fn valid_provider(id: &str) -> bool {
!id.is_empty() && id.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-')
} Type guard
const isKebabProviderId = (s) => typeof s === 'string' && /^[a-z0-9-]+$/.test(s);
Prevention
- Enforce kebab-case naming for providers in config files and tooling.
- Add a config-load check that rejects provider ids outside [a-z0-9-].
- Document the naming rule where providers are defined.
When it happens
Trigger: The `current` provider identifier in the output-token capability scan fails the `ascii_lowercase | digit | '-'` byte check — e.g. contains uppercase, underscores, dots, or slashes.
Common situations: A provider configured with a name like `My_Provider` or `openai.com` instead of the kebab-case identifiers the Runtime expects.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- A pinned task provider requires an explicit model
- agent profile reasoning_effort must be one of: inherit…
- cloud job id must look like cloud_
- Codewhale credentials path must be a directory
- Custom sub-agent requires a non-empty allowed_tools list
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1d1ddca05c23c918.
Report an issue: GitHub.
Appendix: source
Thrown at crates/app-server/src/lib.rs:1657
.get("providers")
.and_then(Value::as_array)
.and_then(|providers| {
providers
.iter()
.find(|provider| provider.get("id").and_then(Value::as_str) == Some(current))
})
.context("Runtime provider is unavailable")?;
let model = requested_model
.or_else(|| provider.get("default_model").and_then(Value::as_str))
.context("maxOutputTokens requires an exact model")?;
if model.trim().is_empty() || model.eq_ignore_ascii_case("auto") {
bail!("maxOutputTokens requires an exact model");
}
if !current
.bytes()
.all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-')
{
bail!("Runtime provider identity is invalid");
}
let mut cursor = None;
let mut seen = std::collections::HashSet::new();
loop {
let mut url =
reqwest::Url::parse(&format!("{}/v1/providers/{current}/models", self.base_url))?;
url.query_pairs_mut().append_pair("limit", "250");
if let Some(cursor) = cursor.as_deref() {
url.query_pairs_mut().append_pair("cursor", cursor);
}
let catalog = self.request_json(self.authed(self.client.get(url))).await?;
if let Some(entry) =
catalog
.get("models")
.and_then(Value::as_array)
.and_then(|models| {
models
.iter()View on GitHub (pinned to 73e0f67d83)