aaif-goose/goose · error
Failed to download: HTTP {}
Error message
Failed to download: HTTP {} What it means
The HTTP response status was neither a 2xx nor 206 Partial Content. Only 5xx, 408 and 429 are treated as transient and retried (up to 10 times with backoff); every other status fails immediately, as do transient statuses once retries are exhausted. The status code is embedded in the message text.
Source
Thrown at crates/goose-download-manager/src/lib.rs:513
let status = response.status();
if status == reqwest::StatusCode::RANGE_NOT_SATISFIABLE {
if file_total > 0 && file_bytes == file_total {
break;
}
*cumulative_bytes = cumulative_bytes.saturating_sub(file_bytes);
file_bytes = 0;
let _ = tokio::fs::remove_file(&partial_path).await;
continue;
}
if !status.is_success() && status != reqwest::StatusCode::PARTIAL_CONTENT {
let is_transient = status.is_server_error()
|| status == reqwest::StatusCode::REQUEST_TIMEOUT
|| status == reqwest::StatusCode::TOO_MANY_REQUESTS;
if !is_transient || retries >= Self::MAX_RETRIES {
anyhow::bail!("Failed to download: HTTP {}", status);
}
retries += 1;
let delay = std::cmp::min(
Self::RETRY_BASE_DELAY * 2u32.saturating_pow(retries - 1),
Self::RETRY_MAX_DELAY,
);
info!(model_id = %model_id, retry = retries, http_status = %status, "Retrying download after transient HTTP error");
Self::cancellable_sleep(delay, downloads, model_id).await?;
continue;
}
if file_bytes > 0 && status == reqwest::StatusCode::OK {
info!(model_id = %model_id, "Server ignored Range header, restarting file from scratch");
// Subtract already-counted partial bytes from cumulative
*cumulative_bytes = cumulative_bytes.saturating_sub(file_bytes);
file_bytes = 0;
let _ = tokio::fs::remove_file(&partial_path).await;
}View on GitHub (pinned to 3810898a74)
Solutions
- Extract the status from the message: 401/403 means authenticate (log in to HuggingFace / supply the bearer token) or use a non-gated mirror
- 404 means verify the repo and exact filename on huggingface.co and fix the model spec
- 429 means back off well past the Retry-After window before restarting
- 5xx means the origin is unhealthy: retry later; the download resumes from the .partial file
Example fix
// before
let result = manager.download_model_sharded_with_bearer_token(id, files, hint, token, None).await;
// after: branch on the embedded HTTP status instead of surfacing a generic error
if let Err(e) = &result {
if let Some(code) = e.to_string().strip_prefix("Failed to download: HTTP ") {
match code.trim() {
"401" | "403" => { /* refresh HF token, then retry */ }
"404" => { /* fix repo/filename in the spec */ }
_ => { /* transient or unknown: schedule a later retry */ }
}
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// confirm reachability and authorization before committing to the transfer
let resp = client.head(url).send().await?;
use reqwest::StatusCode;
match resp.status() {
s if s.is_success() => {}
StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => anyhow::bail!("supply a valid HF token for this gated repo"),
StatusCode::NOT_FOUND => anyhow::bail!("repo/filename wrong: verify on huggingface.co"),
s => anyhow::bail!("preflight got HTTP {s}"),
} Try / catch
if let Some(code) = err.to_string().strip_prefix("Failed to download: HTTP ") {
match code.trim() {
"401" | "403" => { /* authenticate or switch to a non-gated mirror */ }
"404" => { /* fix the repo/filename in the model spec */ }
"429" => { /* back off past Retry-After, then retry */ }
s if s.starts_with('5') => { /* origin outage: retry later; resume is automatic */ }
_ => surface(err),
}
} Prevention
- Authenticate with HuggingFace before downloading gated models so the bearer token is attached
- Validate repo and exact filename against the HF API before queueing multi-GB transfers
- Treat 401/403/404 as permanent (fix input) and only 5xx/408/429 as retryable
When it happens
Trigger: 401/403 when the repo is gated or the bearer token is missing/expired; 404 when the built URL references a nonexistent repo/file or the file was renamed; 400-class errors for malformed requests; 5xx/429 persisting past 10 retries.
Common situations: Downloading gated HF models without huggingface-cli login; a typo in the model spec filename; upstream repo restructure deleting the quantization file; heavy rate limiting during model-release spikes.
Related errors
- Download failed after {} retries: {}
- MLX model {} has no downloadable files
- Model spec '{}' is ambiguous; choose one of: {}
- Download failed: ${response.status} ${response.statusText}
- Failed to access recipe file: {}/{}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/86c093571a1ef78f.
Report an issue: GitHub.