dbt-labs/dbt-core · error · anyhow
GET {url} failed: {status}
Error message
GET {url} failed: {status} What it means
download in crates/dbt-ci/src/sdist.rs performs a GET of a wheel URL and retries transient failures with backoff; when it receives a final non-transient (or retry-exhausted) non-success HTTP status it bails with 'GET {url} failed: {status}'.
Source
Thrown at crates/dbt-ci/src/sdist.rs:222
match http.get(url).send().await {
Ok(resp) => {
let status = resp.status();
if status.is_success() {
return resp
.bytes()
.await
.with_context(|| format!("read body from {url}"));
}
if status.is_server_error() && attempt < max_attempts {
let delay = backoff(attempt);
eprintln!(
"warning: GET {url} got {status}; retrying in {}ms",
delay.as_millis()
);
tokio::time::sleep(delay).await;
continue;
}
bail!("GET {url} failed: {status}");
}
Err(e) if is_transient(&e) && attempt < max_attempts => {
let delay = backoff(attempt);
eprintln!(
"warning: GET {url} failed: {e}; retrying in {}ms",
delay.as_millis()
);
tokio::time::sleep(delay).await;
continue;
}
Err(e) => return Err(anyhow::Error::new(e).context(format!("GET {url}"))),
}
}
}
/// Minimal pyproject wiring up the embedded backend; rich metadata lives in PKG-INFO.
fn render_sdist_pyproject(spec: &Spec, version_pep440: &str) -> String {
let mut out = String::new();View on GitHub (pinned to 0267ce9170)
Solutions
- Check the status: 404 means fix --download-base-url or upload the wheels first; 403 means fix credentials/permissions for the artifact store.
- Verify the exact URL in the message is reachable (curl -I) and that the wheel filename matches what was published.
- Retry later if the status is a 5xx — transient cases are already retried internally, so persistent ones need infra attention.
- Confirm network egress/proxy settings in CI allow reaching the host.
Example fix
# before release-sdist build --download-base-url https://example.com/old-path ... # 404: wheel not there # after release-sdist build --download-base-url https://example.com/wheels/1.2.3 ... # correct path with wheels uploaded first
Defensive patterns
Strategy: retry
Validate before calling
# verify the wheel URL is reachable before the pipeline
url="$BASE_URL/$(basename "$WHEEL")"
curl -fsIL "$url" >/dev/null || { echo "cannot GET $url" >&2; exit 1; } Try / catch
match download(url).await {
Err(e) if e.to_string().starts_with("GET ") => {
eprintln!("wheel download failed permanently: {e:#}");
std::process::exit(1); // inspect status: 404=wrong URL, 403=auth
}
r => r,
} Prevention
- Publish wheels before building the sdist that references them.
- Verify --download-base-url with curl -I before long release runs.
- Keep presigned URLs/AWS credentials fresh for the duration of the job.
- Rely on the built-in backoff for transient 5xx; treat persistent statuses as config problems.
When it happens
Trigger: build_release_sdist downloading a wheel whose GET returns 404 (wrong --download-base-url or missing artifact), 403 (private bucket/registry without credentials), or a persistent 5xx after retries are exhausted.
Common situations: Wheels not yet uploaded (publish order mistake), base URL typo or wrong S3/CodeArtifact path, expired presigned URLs or missing AWS credentials, CDN/proxy returning 5xx consistently.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- failed to download {url}: {last}
- upload {filename} failed: {status} {body}
- `http_status_as_error` is not enabled.
- POST {url}
- GET {url}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/07d88503b585b15b.
Report an issue: GitHub.