astrid-runtime/astrid · error

{label} download failed: HTTP {status}

Error message

{label} download failed: HTTP {status}

What it means

`download_bounded` performs a bounded HTTP GET for release artifacts (archives, checksums, manifests) and bails if the server responds with a non-success status. The `{label}` names which artifact failed, making it clear whether it was the binary, signature, or manifest download.

Source

Thrown at crates/astrid-cli/src/commands/self_update/mod.rs:357

fn integrity_manifest_url(release: &serde_json::Value) -> Result<&str, UpdateStageError> {
    exact_asset_url(release, "BLAKE3SUMS.txt")
        .map_err(|error| UpdateStageError::integrity(error.to_string()))
}

/// Stream a URL into memory under the size cap.
pub(super) async fn download_bounded(
    client: &reqwest::Client,
    url: &str,
    limit: usize,
    label: &str,
) -> anyhow::Result<Vec<u8>> {
    let mut response = client
        .get(url)
        .send()
        .await
        .map_err(|_| anyhow::anyhow!("{label} download failed"))?;
    if !response.status().is_success() {
        bail!("{label} download failed: HTTP {}", response.status());
    }
    if let Some(length) = response.content_length() {
        let length = usize::try_from(length)
            .map_err(|_| anyhow::anyhow!("{label} exceeds {limit} byte limit"))?;
        anyhow::ensure!(length <= limit, "{label} exceeds {limit} byte limit");
    }
    let mut bytes = Vec::new();
    while let Some(chunk) = response
        .chunk()
        .await
        .map_err(|_| anyhow::anyhow!("{label} download failed"))?
    {
        anyhow::ensure!(
            chunk.len() <= limit.saturating_sub(bytes.len()),
            "{label} exceeds {limit} byte limit"
        );
        bytes.extend_from_slice(&chunk);
    }

View on GitHub (pinned to affd8760f4)

Solutions

  1. Check the HTTP status in the message: 404 means the tag/asset is missing — verify the release and asset names exist.
  2. Wait and retry on 403/429 (rate limits) or set an auth token if supported.
  3. Verify network/proxy settings can reach the release host.
  4. Pin an older working version or download the artifact manually from the release page.

Example fix

// before
if !response.status().is_success() {
    bail!("{label} download failed: HTTP {}", response.status());
}
// after
let status = response.status();
if status == reqwest::StatusCode::TOO_MANY_REQUESTS {
    tokio::time::sleep(Duration::from_secs(30)).await;
    // retry once
} else if !status.is_success() {
    bail!("{label} download failed: HTTP {status}");
}
Defensive patterns

Strategy: retry

Validate before calling

curl -fsSI "$URL" >/dev/null && echo reachable || echo "asset missing or host unreachable"

Try / catch

let resp = client.get(url).send().await.map_err(|_| anyhow!("{label} download failed"))?;
let status = resp.status();
if status == StatusCode::TOO_MANY_REQUESTS || status.is_server_error() {
    backoff_retry(up_to = 3);
} else if !status.is_success() {
    bail!("{label} download failed: HTTP {status}");
}

Prevention

When it happens

Trigger: Any caller (download_verify_extract, download, fetch_release_by_tag, resolve_signed_channel) hitting a URL that returns 404 (release/tag or asset missing), 403 (rate-limited or private repo), 5xx (server error), or a redirect to an error page.

Common situations: Self-update pointing at a tag that doesn't exist; GitHub rate limiting unauthenticated requests; asset renamed between releases; corporate proxy blocking the download; channel manifest not yet published for a new release.

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 astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/31a73a59d5a40742. Report an issue: GitHub.