Hmbown/CodeWhale · error

failed to fetch from : HTTP

Error message

failed to fetch {description} from {url}: HTTP {status}
{body}

What it means

fetch_release_json retries UPDATE_HTTP_ATTEMPTS times; when the server answers with a non-success HTTP status that is not retryable (or retries are exhausted), this error is thrown including the description, URL, status code, and the response body. It is the definitive failure of a release-metadata fetch.

Solutions

  1. Read the HTTP status and body in the message: fix auth (GITHUB_TOKEN) for 401/403, or wait for rate-limit reset.
  2. Check network/proxy settings (HTTPS_PROXY) and connectivity to the URL shown.
  3. Verify the release/tag still exists at the printed URL.
  4. Retry later if the status was a transient 5xx/429 and all attempts were consumed.
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight check of the release URL
const res = await fetch(url);
if (res.status === 403 && res.headers.get('x-ratelimit-remaining') === '0') {
  console.error('rate limited; set a token or wait for reset');
}

Try / catch

match fetch_release_json(url, desc, proxy) {
  Ok(body) => body,
  Err(e) if e.to_string().contains("HTTP 403") => {
    // configure auth token / wait for rate-limit reset, then retry once
  }
  Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: GET of the release JSON URL returns 404 (release/tag removed), 403 (rate limited by GitHub without retry eligibility, or proxy blocked), 401, or retries against 5xx/429/408 were exhausted.

Common situations: GitHub API rate limit exhausted (403 with X-RateLimit-Remaining: 0), a corporate proxy blocking the update host, the release artifact renamed or deleted, or offline/VPN DNS hijack returning an error page.

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 Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/0f0c83671f90c3cc. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/update.rs:1423

        .get(url)
        .header(reqwest::header::ACCEPT, "application/vnd.github+json")
        .send()
        .with_context(|| format!("failed to fetch {description} from {url}"))?;
    let status = response.status();
    let body = response
        .text()
        .with_context(|| format!("failed to read {description} response body from {url}"))?;
    Ok((status, body))
}

fn fetch_release_json(url: &str, description: &str, proxy: Option<&Proxy>) -> Result<String> {
    let mut last_error = None;
    for attempt in 1..=UPDATE_HTTP_ATTEMPTS {
        match fetch_release_json_once(url, description, proxy) {
            Ok((status, body)) if status.is_success() => return Ok(body),
            Ok((status, body)) => {
                let error =
                    anyhow!("failed to fetch {description} from {url}: HTTP {status}\n{body}");
                if should_retry_http_status(status) && attempt < UPDATE_HTTP_ATTEMPTS {
                    last_error = Some(error);
                    sleep_before_update_retry(attempt);
                    continue;
                }
                return Err(error);
            }
            Err(error) if attempt < UPDATE_HTTP_ATTEMPTS => {
                last_error = Some(error);
                sleep_before_update_retry(attempt);
            }
            Err(error) => return Err(error),
        }
    }
    Err(last_error.unwrap_or_else(|| anyhow!("failed to fetch {description} from {url}")))
}

fn should_retry_http_status(status: reqwest::StatusCode) -> bool {

View on GitHub (pinned to 73e0f67d83)