rust-lang/rust · error · anyhow::Error
Cannot fetch metrics from {url}: {} {}
Error message
Cannot fetch metrics from {url}: {}
{} What it means
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.
Source
Thrown at src/ci/citool/src/metrics.rs:92
Ok(jobs)
}
pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoot> {
// Best effort cache to speed-up local re-executions of citool
let cache_path = PathBuf::from(".citool-cache").join(sha).join(format!("{job_name}.json"));
if cache_path.is_file() {
if let Ok(metrics) = std::fs::read_to_string(&cache_path)
.map_err(|err| err.into())
.and_then(|data| anyhow::Ok::<JsonRoot>(serde_json::from_str::<JsonRoot>(&data)?))
{
return Ok(metrics);
}
}
let url = get_metrics_url(job_name, sha);
let mut response = ureq::get(&url).call()?;
if !response.status().is_success() {
return Err(anyhow::anyhow!(
"Cannot fetch metrics from {url}: {}\n{}",
response.status(),
response.body_mut().read_to_string()?
));
}
let data: JsonRoot = response
.body_mut()
.read_json()
.with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?;
if let Ok(_) = std::fs::create_dir_all(cache_path.parent().unwrap()) {
if let Ok(data) = serde_json::to_string(&data) {
let _ = std::fs::write(cache_path, data);
}
}
Ok(data)
}View on GitHub (pinned to 7088e4b63a)
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.
Example fix
null
Defensive patterns
Strategy: retry
Validate before calling
// Optionally probe the URL before relying on it.
let resp = ureq::get(&url).call()?;
if !resp.status().is_success() {
eprintln!("Metrics for {url} unavailable ({}); skipping parent comparison", resp.status());
} Try / catch
match download_job_metrics(job_name, sha) {
Ok(m) => m,
Err(e) => {
if e.to_string().contains("Cannot fetch metrics") {
// Transient or missing artifact; degrade gracefully if metrics are optional
eprintln!("warning: {e:#}");
continue;
}
return Err(e);
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot get jobs of workflow run {workflow_run_id}: {status}
- cannot deserialize metrics from {url}
- git command failed
- duplicate job name `{job_name}` in section `{section}`
- PR job `{}` differs from corresponding Auto job `{}` in conf
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/2d29ed47e5fac942.
Report an issue: GitHub.