zeroclaw-labs/zeroclaw · error · anyhow::Error
{} model list failed at {url}: HTTP {status}
Error message
{} model list failed at {url}: HTTP {status} What it means
OpenAiCompatibleModelProvider::list_models GETs {base_url}/models when a credential resolves or public_model_listing is enabled. The endpoint answered but with a non-2xx status; the message embeds the provider display name, the full URL, and the HTTP status so the failure is directly attributable.
Source
Thrown at crates/zeroclaw-providers/src/compatible.rs:2678
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({
"model_provider": &self.name,
"url": &url,
"phase": "model_list_request",
"error": super::format_error_chain(&e),
})),
"compatible: model list request failed"
);
anyhow::Error::msg(format!(
"{} model list request failed: {url}: {e}",
self.name
))
})?;
if !response.status().is_success() {
let status = response.status();
anyhow::bail!("{} model list failed at {url}: HTTP {status}", self.name);
}
let body: ModelsResponse = response.json().await.map_err(|e| {
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({
"model_provider": &self.name,
"phase": "model_list_parse",
"error": super::format_error_chain(&e),
})),
"compatible: model list returned invalid JSON"
);
anyhow::Error::msg(format!(
"{} model list returned invalid JSON: {e}",
self.name
))
})?;View on GitHub (pinned to 88bb9c8533)
Solutions
- Reproduce directly: curl -i {base_url}/models with the same Authorization header and read the status
- Fix base_url so it points at the API root that serves /models (usually ends in /v1, no trailing slash)
- Verify the API key is valid and unexpired for that provider
- If the server truly has no /models, configure a static model list on the alias or enable the models_dev/openrouter catalog fallback
Example fix
# before [model_provider.local] family = "compatible" base_url = "http://localhost:11434" # after [model_provider.local] family = "compatible" base_url = "http://localhost:11434/v1"
Defensive patterns
Strategy: try-catch
Validate before calling
// Sanity-check the URL shape before trusting it for listing
let url = reqwest::Url::parse(&format!("{base_url}/models"))?;
if !url.scheme().starts_with("http") || base_url.ends_with('/') {
anyhow::bail!("base_url must not end with '/' and must be a valid http(s) root");
} Try / catch
match provider.list_models().await {
Ok(models) => Ok(models),
Err(e) => {
let msg = e.to_string();
if msg.contains("HTTP 429") || msg.contains("HTTP 5") {
backoff_retry(/* ... */).await // transient: retry with jitter
} else if msg.contains("HTTP 401") || msg.contains("HTTP 403") {
/* credential problem: surface to user, do not retry */
Err(e)
} else {
Err(e) // 404 etc: fix base_url / static list
}
}
} Prevention
- curl the /models endpoint once when adding a new alias
- Standardize base_url to end at the version segment (e.g. /v1) with no trailing slash
- Keep a static model list on aliases whose servers lack /models
- Treat 401 as config drift - alert on it instead of retrying
When it happens
Trigger: 401/403 from a bad or expired API key; 404 when base_url is wrong (missing or doubled /v1, or trailing slash) or the server does not expose /models; 429 rate limiting; 5xx from the upstream gateway.
Common situations: base_url set to the host root when the API lives under /v1 (or /v1/v1 after duplication); local OpenAI-compatible servers with different routing; expired tokens; gateways behind flaky proxies.
Related errors
- live model listing is not supported for this model_provider
- {} API error ({status}): {sanitized}
- OpenAiCompatibleBuilder: base_url() is required
- ACP returned unknown optionId: {option_id}
- matrix: configure either `access_token` or `password`
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/49e97424e5b5d0c8.
Report an issue: GitHub.