sigoden/aichat · error · anyhow::Error

Invalid status

Error message

Invalid status: {}

What it means

fetch_with_loaders performs an HTTP GET and bails with 'Invalid status: <code>' when the response status is not a success (non-2xx). This converts any HTTP error status (404, 401, 403, 429, 5xx) into a library error including the status code.

Solutions

  1. Check the status code in the message: fix auth (401/403) or correct the URL (404)
  2. Add required headers/cookies or use an authenticated client for gated resources
  3. Retry with backoff for 429/5xx responses
  4. Configure a url_loader (e.g. a headless-browser loader) for pages that reject plain GETs
  5. Verify network/proxy access to the host

Example fix

// before: fetching a gist without auth -> 404
let doc = load_url("https://gist.github.com/private/abc").await?;
// after: use raw authenticated URL or a loader with token
let doc = load_url("https://gist.githubusercontent.com/.../raw?token=...").await?;
Defensive patterns

Strategy: retry

Validate before calling

async function reachable(url) {
  try {
    const res = await fetch(url, { method: 'HEAD' });
    return res.ok;
  } catch { return false; }
}

Try / catch

try {
  const doc = await loadUrl(url);
} catch (e) {
  const m = e.message.match(/Invalid status: (\d+)/);
  if (m) {
    const code = +m[1];
    if (code === 429 || code >= 500) await retryWithBackoff(() => loadUrl(url));
    else console.error(`non-retryable status ${code} for ${url}`);
  }
}

Prevention

When it happens

Trigger: load_url / load_documents fetching a URL that returns non-2xx: dead link (404), auth-required resource (401/403), rate limiting (429), or server errors (5xx).

Common situations: URL points to a private/auth-gated resource; page moved or deleted; scraping endpoints that block non-browser clients; temporary provider outage or rate limit.

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 sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/db099d36362658fa. Report an issue: GitHub.

Appendix: source

Thrown at src/utils/request.rs:85

    Ok(output)
}

pub async fn fetch_with_loaders(
    loaders: &HashMap<String, String>,
    path: &str,
    allow_media: bool,
) -> Result<(String, String)> {
    if let Some(loader_command) = loaders.get(URL_LOADER) {
        let contents = run_loader_command(path, URL_LOADER, loader_command)?;
        return Ok((contents, DEFAULT_EXTENSION.into()));
    }
    let client = match *CLIENT {
        Ok(ref client) => client,
        Err(ref err) => bail!("{err}"),
    };
    let mut res = client.get(path).send().await?;
    if !res.status().is_success() {
        bail!("Invalid status: {}", res.status());
    }
    let content_type = res
        .headers()
        .get(CONTENT_TYPE)
        .and_then(|v| v.to_str().ok())
        .map(|v| match v.split_once(';') {
            Some((mime, _)) => mime.trim(),
            None => v,
        })
        .map(|v| v.to_string())
        .unwrap_or_else(|| {
            format!(
                "_/{}",
                get_patch_extension(path).unwrap_or_else(|| DEFAULT_EXTENSION.into())
            )
        });
    let mut is_media = false;
    let extension = match content_type.as_str() {

View on GitHub (pinned to 82976d349a)