{"record":{"id":"3ba746995f761034","repo":"astrid-runtime/astrid","slug":"label-download-failed","errorCode":null,"errorMessage":"{label} download failed","messagePattern":"(.+?) download failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/self_update/mod.rs","lineNumber":355,"sourceCode":"}\n\nfn integrity_manifest_url(release: &serde_json::Value) -> Result<&str, UpdateStageError> {\n    exact_asset_url(release, \"BLAKE3SUMS.txt\")\n        .map_err(|error| UpdateStageError::integrity(error.to_string()))\n}\n\n/// Stream a URL into memory under the size cap.\npub(super) async fn download_bounded(\n    client: &reqwest::Client,\n    url: &str,\n    limit: usize,\n    label: &str,\n) -> anyhow::Result<Vec<u8>> {\n    let mut response = client\n        .get(url)\n        .send()\n        .await\n        .map_err(|_| anyhow::anyhow!(\"{label} download failed\"))?;\n    if !response.status().is_success() {\n        bail!(\"{label} download failed: HTTP {}\", response.status());\n    }\n    if let Some(length) = response.content_length() {\n        let length = usize::try_from(length)\n            .map_err(|_| anyhow::anyhow!(\"{label} exceeds {limit} byte limit\"))?;\n        anyhow::ensure!(length <= limit, \"{label} exceeds {limit} byte limit\");\n    }\n    let mut bytes = Vec::new();\n    while let Some(chunk) = response\n        .chunk()\n        .await\n        .map_err(|_| anyhow::anyhow!(\"{label} download failed\"))?\n    {\n        anyhow::ensure!(\n            chunk.len() <= limit.saturating_sub(bytes.len()),\n            \"{label} exceeds {limit} byte limit\"\n        );","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/self_update/mod.rs#L337-L373","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","solutions":["Check network connectivity to github.com (and the configured repo host) and retry.","Configure proxy environment variables (HTTPS_PROXY/HTTP_PROXY) if behind a corporate proxy.","Fix DNS if resolution is failing (try curl to the release URL).","Retry later if GitHub is having an outage."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-flight connectivity check before updating\ncurl -fsSI https://api.github.com/ >/dev/null || { echo \"github.com unreachable\"; exit 1; }","typeGuard":null,"tryCatchPattern":"for attempt in 0..3 {\n    match download_bounded(client, url, label, limit).await {\n        Ok(bytes) => break Ok(bytes),\n        Err(e) if attempt < 2 && e.to_string().ends_with(\"download failed\") => {\n            tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await;\n        }\n        Err(e) => break Err(e),\n    }\n}","preventionTips":["Set HTTPS_PROXY correctly in corporate environments.","Avoid running self update from air-gapped or firewalled hosts.","Retry on transient failures with backoff.","Check provider status pages during widespread outages."],"tags":["network","download","self-update","http"],"backgroundTag":"network-request-failed","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}