ducaale/xh · error
Bad Content-Range header
Error message
Bad Content-Range header
What it means
The Content-Range header value retrieved during a resumed download is not valid UTF-8 (or otherwise not a valid header string), so it cannot be parsed. The client rejects it before attempting range parsing.
Solutions
- Restart the download without resume (offset 0).
- Inspect the raw response headers (curl -v) to identify the malformed value.
- Update/bypass the proxy or middleware corrupting headers.
- If the server is under your control, fix its Content-Range emission to valid ASCII per RFC 9110.
Defensive patterns
Strategy: fallback
Validate before calling
if let Some(v) = resp.headers().get(header::CONTENT_RANGE) {
if v.to_str().is_err() {
// treat as non-resumable, restart download
}
} Type guard
fn valid_content_range(resp: &Response) -> Option<&str> {
resp.headers().get(header::CONTENT_RANGE)?.to_str().ok()
} Try / catch
match download_file(url, Some(offset)) {
Err(e) if e.to_string().contains("Bad Content-Range") => download_file(url, None),
other => other,
} Prevention
- Treat any unparsable Content-Range as 'not resumable' and restart.
- Inspect raw headers with curl -v when a server misbehaves.
- Whitelist only trusted servers for resume operations.
- Keep a retry counter to avoid resume loops against broken servers.
When it happens
Trigger: download_file called with Some(resume) and response.headers().get(CONTENT_RANGE) returns a HeaderValue whose to_str() fails because the header bytes are not visible ASCII/UTF-8.
Common situations: Misbehaving or malicious server/proxy emitting non-ASCII bytes in headers; corrupted response through broken middleware; extremely unusual custom server implementations.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Can't parse Content-Range header, can't resume download
- Content-Range has wrong start
- Missing Content-Range header
- Invalid Content-Range
- Content-Range has wrong end
AI-assisted analysis of ducaale/xh@2404aceecc (2026-09-13).
Data as JSON: /api/errors/7bb52c643255c8f7.
Report an issue: GitHub.
Appendix: source
Thrown at src/download.rs:212
buffer = Box::new(open_opts.open(&dest_name)?);
} else if test_pretend_term() || io::stdout().is_terminal() {
let (new_name, handle) = open_new_file(get_file_name(&response, orig_url).into())?;
dest_name = new_name;
buffer = Box::new(handle);
} else {
dest_name = "<stdout>".into();
buffer = Box::new(io::stdout());
}
let starting_length: u64;
let total_length: Option<u64>;
if let Some(resume) = resume {
let header = response
.headers()
.get(CONTENT_RANGE)
.ok_or_else(|| anyhow!("Missing Content-Range header"))?
.to_str()
.map_err(|_| anyhow!("Bad Content-Range header"))?;
starting_length = resume;
total_length = Some(total_for_content_range(header, starting_length)?);
} else {
starting_length = 0;
total_length = get_content_length(response.headers());
}
let starting_time = Instant::now();
let pb = if quiet {
// Still counts the downloaded bytes, it just doesn't display anything.
ProgressBar::hidden()
} else if let Some(total_length) = total_length {
eprintln!(
"Downloading {} to {:?}",
HumanBytes(total_length - starting_length),
dest_name
);View on GitHub (pinned to 2404aceecc)