astrid-runtime/astrid · error

download failed

Error message

{label} download failed

What it means

download_bounded performs the HTTP GET for update artifacts; if reqwest fails to even send the request or establish a connection, it maps the error to this labeled failure. Note the related but distinct HTTP-status failure uses the ': HTTP <status>' variant — this message specifically means the request never completed successfully at the transport level.

Solutions

  1. Check network connectivity to github.com (and the configured repo host) and retry.
  2. Configure proxy environment variables (HTTPS_PROXY/HTTP_PROXY) if behind a corporate proxy.
  3. Fix DNS if resolution is failing (try curl to the release URL).
  4. Retry later if GitHub is having an outage.
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight connectivity check before updating
curl -fsSI https://api.github.com/ >/dev/null || { echo "github.com unreachable"; exit 1; }

Try / catch

for attempt in 0..3 {
    match download_bounded(client, url, label, limit).await {
        Ok(bytes) => break Ok(bytes),
        Err(e) if attempt < 2 && e.to_string().ends_with("download failed") => {
            tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await;
        }
        Err(e) => break Err(e),
    }
}

Prevention

When it happens

Trigger: fetching a release, archive, bundle, or manifest where the request errors out: DNS resolution failure, connection refused/reset, TLS handshake failure, or timeout in reqwest's send().

Common situations: Self-update run offline or behind a firewall blocking github.com; corporate proxy without proper env config; transient network blips; DNS problems in CI containers.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/3ba746995f761034. Report an issue: GitHub.

Appendix: source

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

}

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"
        );

View on GitHub (pinned to affd8760f4)