{"record":{"id":"e56f919a69dd7051","repo":"Hmbown/CodeWhale","slug":"failed-to-fetch-description-from-url","errorCode":null,"errorMessage":"failed to fetch {description} from {url}","messagePattern":"failed to fetch (.+?) from (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/update.rs","lineNumber":1438,"sourceCode":"            Ok((status, body)) if status.is_success() => return Ok(body),\n            Ok((status, body)) => {\n                let error =\n                    anyhow!(\"failed to fetch {description} from {url}: HTTP {status}\\n{body}\");\n                if should_retry_http_status(status) && attempt < UPDATE_HTTP_ATTEMPTS {\n                    last_error = Some(error);\n                    sleep_before_update_retry(attempt);\n                    continue;\n                }\n                return Err(error);\n            }\n            Err(error) if attempt < UPDATE_HTTP_ATTEMPTS => {\n                last_error = Some(error);\n                sleep_before_update_retry(attempt);\n            }\n            Err(error) => return Err(error),\n        }\n    }\n    Err(last_error.unwrap_or_else(|| anyhow!(\"failed to fetch {description} from {url}\")))\n}\n\nfn should_retry_http_status(status: reqwest::StatusCode) -> bool {\n    status.is_server_error()\n        || status == reqwest::StatusCode::REQUEST_TIMEOUT\n        || status == reqwest::StatusCode::TOO_MANY_REQUESTS\n}\n\nfn sleep_before_update_retry(attempt: usize) {\n    std::thread::sleep(Duration::from_millis(\n        UPDATE_HTTP_RETRY_DELAY_MS * attempt as u64,\n    ));\n}\n\nfn fetch_latest_release_from_url(url: &str, proxy: Option<&Proxy>) -> Result<Release> {\n    let body = fetch_release_json(url, \"release info\", proxy)?;\n    let release: Release = serde_json::from_str(&body).with_context(|| {\n        format!(\"failed to parse release JSON from GitHub API. Response: {body}\")","sourceCodeStart":1420,"sourceCodeEnd":1456,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/update.rs#L1420-L1456","documentation":"After the retry loop in fetch_release_json, if last_error is None (no HTTP-status error was ever recorded), the code falls back to this generic error. This happens when all attempts looped through retryable statuses without storing an error, or defensively when the loop exited without a success or a stored error. It omits status/body because none was captured.","triggerScenarios":"Every attempt returned a retryable failure status (5xx/408/429) and the final attempt's error path stores last_error but the loop structure exits via the fallback line, or no attempt recorded an error before the loop ended.","commonSituations":"Sustained upstream outage of the release host during an update; a proxy returning retryable 502/503 for every attempt over the whole retry window.","solutions":["Retry the update later — the release host was persistently returning retryable errors.","Check the host's status page for an outage.","Inspect proxy/firewall interception that might return 502/503 for all requests.","Increase visibility by running with verbose logging to see the per-attempt statuses."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// probe connectivity to the host before updating\nconst res = await fetch(baseUrl + '/releases/latest', { method: 'HEAD' });\nif (!res.ok) console.error('release host unreachable:', res.status);","typeGuard":null,"tryCatchPattern":"match fetch_release_json(url, desc, proxy) {\n  Err(e) if e.to_string().ends_with(\"failed to fetch\") || !e.to_string().contains(\"HTTP\") => {\n    // persistent upstream failure: back off significantly and retry later\n  }\n  other => other,\n}","preventionTips":["Check the provider status page before scripted updates.","Add your own backoff wrapper around update commands.","Bypass intercepting proxies that answer every request with 5xx."],"tags":["http","update","network","retry"],"backgroundTag":"http-request-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}