Hmbown/CodeWhale · error
Failed to list models: HTTP {status}: {error_text}
Error message
Failed to list models: HTTP {status}: {error_text} What it means
`list_models()` issues `GET {base_url}/models` through the retrying transport and bails when the HTTP status is not 2xx. The response body is read with a 64KB cap and sanitized (provider display name, status code, secret redaction) before being embedded, so the message shows the provider's own error text safely. This is the model-picker's discovery call.
Source
Thrown at crates/tui/src/client.rs:2105
.to_string();
Ok(translated)
}
/// List available models from the provider.
pub async fn list_models(&self) -> Result<Vec<AvailableModel>> {
let url = api_url(&self.base_url, "models");
let response = self.send_with_retry(|| self.http_client.get(&url)).await?;
let status = response.status();
if !status.is_success() {
let raw_error_text = bounded_error_text(response, ERROR_BODY_MAX_BYTES).await;
let error_text = sanitize_http_error_body(
Some(self.api_provider.display_name()),
status.as_u16(),
&raw_error_text,
);
anyhow::bail!("Failed to list models: HTTP {status}: {error_text}");
}
let response_text = response
.text()
.await
.context("Failed to read models response body")?;
parse_models_response(&response_text)
.map(|models| apply_provider_model_cutline(self.api_provider, models))
}
/// The catalog provider id for this client (the `ProviderKind` slug, falling
/// back to the `ApiProvider` slug for legacy variants without a kind). This
/// is the id used as the cache scope and `CatalogOffering.provider`.
fn catalog_provider_id(&self) -> String {
self.api_provider
.kind()
.map(|kind| kind.as_str().to_string())
.unwrap_or_else(|| self.api_provider.as_str().to_string())View on GitHub (pinned to 8880682c63)
Solutions
- Check the status code in the message: 401/403 → fix the API key for that provider; 404 → the endpoint does not serve `/models`.
- Correct the base_url so `{base_url}/models` resolves (verify with `curl -s $BASE_URL/models -H "Authorization: Bearer $KEY"`).
- If the server genuinely has no models route, configure the model id explicitly instead of relying on listing.
- 429/5xx: wait and retry; the error text from the provider usually states the quota or outage reason.
Example fix
# before base_url = "https://my-gateway/api" # 404 on /api/models # after base_url = "https://my-gateway/api/v1" # /api/v1/models exists
Defensive patterns
Strategy: try-catch
Validate before calling
// Cheap preflight before rendering a model picker.
async fn models_endpoint_ok(base_url: &str, key: &str) -> bool {
let url = format!("{base_url}/models");
reqwest::Client::new().get(&url).bearer_auth(key).send().await
.is_ok_and(|r| r.status().is_success())
} Try / catch
match client.list_models().await {
Ok(models) => render_picker(models),
Err(e) if e.to_string().contains("Failed to list models: HTTP 404") => {
// endpoint has no /models route: fall back to manual model entry
render_manual_model_entry(),
}
Err(e) if e.to_string().contains("HTTP 401") || e.to_string().contains("HTTP 403") => prompt_for_api_key(),
Err(e) => show_error(e),
} Prevention
- Treat model listing as best-effort: cache the last successful list and offer manual model entry when it fails.
- Verify base_url/key with `codewhale doctor` after changing provider config.
- Check `{base_url}/models` with curl when onboarding a new OpenAI-compatible gateway.
When it happens
Trigger: 401/403 when the API key is missing, wrong, or lacks scope; 404 when the provider or proxy does not expose `/models` at the configured base_url (wrong `/v1` prefix, gateway without a models route); 429 when rate-limited before listing; 5xx upstream outages.
Common situations: Custom OpenAI-compatible servers (llama.cpp, some vLLM/LiteLLM setups) that omit or disable the models listing route; base_url with a doubled or missing version path; expired or mistyped API key; corporate proxies blocking GET on unknown paths.
Related errors
- FIM API error: HTTP {status}: {error_text}
- iLink API ${endpoint} failed: HTTP ${response.status} — ${te
- Refusing insecure base URL '{display_base_url}'. Loopback h
- Speech synthesis failed: HTTP {status}: {error_text}
- Anthropic API error (HTTP {status} {error_type}): {message}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/09a9d14b0665b055.
Report an issue: GitHub.