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

  1. 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).
  2. Re-test the key directly with curl against the provider's /models endpoint to confirm credentials and URL work outside the app.
  3. Handle 429 by waiting and retrying with backoff; 5xx is a provider-side outage, retry later.
  4. 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

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)