tonhowtf/omniget · error
HTTP {}: {}
Error message
HTTP {}: {} What it means
The models() function in ai_keys.rs performs an HTTP request to a provider's model-list endpoint and throws this error when the response status is not a success (2xx). It includes the numeric status code and up to 200 chars of the response body so the developer can see the provider's own error message. It wraps any non-2xx outcome: 401/403 for bad keys, 404 for wrong base_url paths, 429 for rate limits, 5xx for provider outages.
Solutions
- Check the status code and body in the error message: 401/403 means fix or re-enter the API key via the key manager; 404 means fix base_url to point at the API root (usually includes /v1).
- Re-test the key directly with curl against the provider's /models endpoint to confirm credentials and URL work outside the app.
- Handle 429 by waiting and retrying with backoff; 5xx is a provider-side outage, retry later.
- If the provider changed its API routes, update the base_url stored for the key entry.
Example fix
// before let base = "https://api.openai.com"; // missing /v1 -> 404 // after let base = "https://api.openai.com/v1";
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check the endpoint before calling models()
let resp = reqwest::Client::new()
.get(format!("{base_url}/models"))
.bearer_auth(&key)
.send().await?;
if !resp.status().is_success() {
eprintln!("provider returned {} — fix key/base_url first", resp.status());
} Type guard
fn is_ok_status(status: u16) -> bool { (200..300).contains(&status) } Try / catch
match models(id).await {
Ok(list) => use(list),
Err(e) if e.to_string().starts_with("HTTP 401") || e.to_string().starts_with("HTTP 403") => prompt_reenter_key(),
Err(e) if e.to_string().starts_with("HTTP 429") => retry_with_backoff(),
Err(e) => show_error(e),
} Prevention
- Rotate and re-test API keys regularly
- Store the full API base (including /v1), not the site root
- Handle 429 with exponential backoff
- Watch provider status pages for 5xx outages
When it happens
Trigger: Calling models() for a key whose provider endpoint returns 401 (invalid/revoked API key), 404 (base_url missing /models path or wrong route), 429 (rate limited), or 5xx; also when the request goes through but the provider rejects the bearer token.
Common situations: Expired or rotated API keys still stored in the key manager; base_url set to the site root instead of the API base (e.g. missing /v1); provider temporarily down; free-tier rate limits hit while listing models.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/b55ff3e1c79d3da8.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/ai_keys.rs:356
entry.base_url, entry.key
))
.send()
.await?
.error_for_status()
.map_err(|e| anyhow!("Gemini: {}", e))?
.json()
.await?
}
_ => {
let mut req = c.get(format!("{}/models", entry.base_url));
if !entry.key.is_empty() {
req = req.bearer_auth(&entry.key);
}
let resp = req.send().await?;
let status = resp.status();
let text = resp.text().await.unwrap_or_default();
if !status.is_success() {
return Err(anyhow!(
"HTTP {}: {}",
status.as_u16(),
text.chars().take(200).collect::<String>()
));
}
serde_json::from_str(&text).map_err(|_| {
anyhow!(
"resposta nao e JSON: {}",
text.chars().take(120).collect::<String>()
)
})?
}
};
let arr = json
.get("data")
.or_else(|| json.get("models"))
.and_then(|v| v.as_array())
.cloned()View on GitHub (pinned to 8600b91f42)