{"record":{"id":"2d29ed47e5fac942","repo":"rust-lang/rust","slug":"cannot-fetch-metrics-from-url","errorCode":null,"errorMessage":"Cannot fetch metrics from {url}: {}\n{}","messagePattern":"Cannot fetch metrics from (.+?): (.+?)\n(.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/ci/citool/src/metrics.rs","lineNumber":92,"sourceCode":"    Ok(jobs)\n}\n\npub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoot> {\n    // Best effort cache to speed-up local re-executions of citool\n    let cache_path = PathBuf::from(\".citool-cache\").join(sha).join(format!(\"{job_name}.json\"));\n    if cache_path.is_file() {\n        if let Ok(metrics) = std::fs::read_to_string(&cache_path)\n            .map_err(|err| err.into())\n            .and_then(|data| anyhow::Ok::<JsonRoot>(serde_json::from_str::<JsonRoot>(&data)?))\n        {\n            return Ok(metrics);\n        }\n    }\n\n    let url = get_metrics_url(job_name, sha);\n    let mut response = ureq::get(&url).call()?;\n    if !response.status().is_success() {\n        return Err(anyhow::anyhow!(\n            \"Cannot fetch metrics from {url}: {}\\n{}\",\n            response.status(),\n            response.body_mut().read_to_string()?\n        ));\n    }\n    let data: JsonRoot = response\n        .body_mut()\n        .read_json()\n        .with_context(|| anyhow::anyhow!(\"cannot deserialize metrics from {url}\"))?;\n\n    if let Ok(_) = std::fs::create_dir_all(cache_path.parent().unwrap()) {\n        if let Ok(data) = serde_json::to_string(&data) {\n            let _ = std::fs::write(cache_path, data);\n        }\n    }\n\n    Ok(data)\n}","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/rust-lang/rust/blob/7088e4b63a9516ebfbfe2ab2d999cf01a528ac14/src/ci/citool/src/metrics.rs#L74-L110","documentation":"Thrown by download_job_metrics when the HTTP GET to the ci-artifacts.rust-lang.org metrics URL returns a non-success status code. The message includes the URL, the HTTP status, and the response body text, so the upstream error (e.g. 404 for a missing artifact, 403 for access denied) is visible.","triggerScenarios":"Requesting metrics for a (job_name, sha) pair that has no stored artifact (typo in job name or SHA, or the build never published metrics); the artifacts bucket is temporarily unavailable; a network proxy returns an error status.","commonSituations":"Comparing against a parent commit SHA whose build failed before publishing metrics; local citool run pointed at a SHA that only exists locally and was never built by CI; transient ci-artifacts outage.","solutions":["Verify the SHA exists on the rust-lang/rust remote and that its CI run completed and published artifacts.","Confirm the job_name matches an actual CI job (see the available-jobs list).","Delete the .citool-cache directory to rule out a stale/partial cache, then retry.","If the status is 5xx, retry after the ci-artifacts service recovers."],"exampleFix":"null","handlingStrategy":"retry","validationCode":"// Optionally probe the URL before relying on it.\nlet resp = ureq::get(&url).call()?;\nif !resp.status().is_success() {\n    eprintln!(\"Metrics for {url} unavailable ({}); skipping parent comparison\", resp.status());\n}","typeGuard":null,"tryCatchPattern":"match download_job_metrics(job_name, sha) {\n    Ok(m) => m,\n    Err(e) => {\n        if e.to_string().contains(\"Cannot fetch metrics\") {\n            // Transient or missing artifact; degrade gracefully if metrics are optional\n            eprintln!(\"warning: {e:#}\");\n            continue;\n        }\n        return Err(e);\n    }\n}","preventionTips":["Only request metrics for SHAs whose CI run is known to have completed and published artifacts.","Treat 404 as 'no parent metrics' rather than a hard failure when metrics are best-effort.","Keep the .citool-cache warm to avoid repeated network probes."],"tags":["ci","citool","metrics","network","http"],"backgroundTag":null,"analyzedSha":"7088e4b63a9516ebfbfe2ab2d999cf01a528ac14","analyzedAt":"2026-08-10T14:17:03.603Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}