cjpais/Handy · error · anyhow::Error
server returned Content-Range starting at {:?}, expected {}
Error message
server returned Content-Range starting at {:?}, expected {} What it means
On HTTP 206 the downloader parses the Content-Range header and requires the start offset to equal resume_from exactly (the partial's byte length). A reply starting anywhere else — including a missing or unparseable Content-Range, where starts_at is None — would silently corrupt the file on append, so the partial is deleted and the error returned.
Source
Thrown at src-tauri/src/managers/model/download.rs:274
resume_from = 0;
}
if !response.status().is_success() {
return Err(anyhow::anyhow!(
"server returned HTTP {}",
response.status()
));
}
// On a 206, trust but verify the offset: a reply starting anywhere but
// exactly our partial's end would silently corrupt the file on append.
if resume_from > 0 && response.status() == reqwest::StatusCode::PARTIAL_CONTENT {
let starts_at = response
.headers()
.get(reqwest::header::CONTENT_RANGE)
.and_then(|v| v.to_str().ok())
.and_then(content_range_start);
if starts_at != Some(resume_from) {
let _ = fs::remove_file(partial_path);
return Err(anyhow::anyhow!(
"server returned Content-Range starting at {:?}, expected {}",
starts_at,
resume_from
));
}
}
// When the catalog pins the size, a server advertising a different
// total is already misbehaving — reject before writing anything.
if let (Some(expected), Some(len)) = (expected_size, response.content_length()) {
if resume_from + len != expected {
return Err(anyhow::anyhow!(
"server advertises {} bytes, expected {}",
resume_from + len,
expected
));
}
}
View on GitHub (pinned to 98a4d80cce)
Solutions
- Retry — the partial was removed, so the next attempt downloads from byte 0
- If it persists, test the host: curl -r <offset>- <url> -D - and inspect the Content-Range header
- Switch to a Range-correct source such as the official HuggingFace endpoint
Defensive patterns
Strategy: retry
Try / catch
match downloader.download_http_resumable(...).await {
Ok(outcome) => Ok(outcome),
Err(e) if e.to_string().contains("Content-Range starting at") => {
// partial deleted by the guard; retry downloads from byte 0
downloader.download_http_resumable(...).await
}
Err(e) => Err(e),
} Prevention
- Validate Range support of a mirror once with curl -r before relying on resume
- Treat a 206 without an exact Content-Range as a broken server, never append
- Prefer endpoints with correct HTTP/1.1 Range semantics (HF, major CDNs)
When it happens
Trigger: Server replies 206 but restarts from byte 0; Content-Range header missing or malformed so content_range_start returns None; object changed between the original download and the resume so offsets no longer align.
Common situations: Cheap mirrors or CDNs with broken Range semantics; hand-rolled static servers that label every response 206; proxies that rewrite range responses.
Related errors
- server object ends before the expected size (HTTP 416)
- server advertises {} bytes, expected {}
- transfer stalled: no data for {}s
- transfer stalled: no progress for {}s
- Hugging Face download failed after {} attempt(s): {}
AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16).
Data as JSON: /api/errors/88cecbb212f6cdb8.
Report an issue: GitHub.