jdx/mise · error
server returned an invalid Content-Range response
Error message
server returned an invalid Content-Range response
What it means
During a resumed download, mise sent a Range request and the server answered 206 Partial Content, but the Content-Range header could not be parsed as a byte range (missing, malformed, or an 'unsatisfied'/'other' form). mise restarts the download once without resume; if the retry also fails to yield a parseable byte Content-Range, it gives up with this error. It protects against writing partial bytes at the wrong offset.
Source
Thrown at src/http.rs:1024
if resp.status() == StatusCode::PARTIAL_CONTENT {
let Some((state, _)) = resume else {
partial.clear()?;
if !restarted_without_resume {
restarted_without_resume = true;
continue;
}
bail!("server returned partial content without a resumable request");
};
let content_range = resp
.headers()
.get(CONTENT_RANGE)
.and_then(|value| value.to_str().ok())
.and_then(parse_content_range);
let Some(ParsedContentRange::Bytes { start, end, total }) = content_range
else {
partial.clear()?;
if restarted_without_resume {
bail!("server returned an invalid Content-Range response");
}
restarted_without_resume = true;
continue;
};
let validator = response_validator(resp.headers());
let response_length_matches = resp
.content_length()
.is_none_or(|length| length == end - start + 1);
if start != offset
|| end + 1 != total
|| !response_length_matches
|| state.total_size.is_some_and(|expected| expected != total)
|| validator
.as_ref()
.is_some_and(|value| !value.matches(&state.validator))
{
partial.clear()?;
if restarted_without_resume {View on GitHub (pinned to afd2eddd3a)
Solutions
- Clear the partial download file/state (delete the .part file) and retry the download from scratch.
- Retry later or from a different network to bypass the misbehaving proxy/CDN.
- If you control the server/proxy, fix it to emit a valid 'Content-Range: bytes start-end/total' header on 206 responses.
Example fix
// before: download via corporate proxy that mangles Content-Range export HTTPS_PROXY=http://proxy.corp:8080; mise install node@22 // after: bypass the proxy for tool downloads export NO_PROXY=github.com,objects.githubusercontent.com; mise install node@22
Defensive patterns
Strategy: retry
Validate before calling
let range = headers.get("content-range").and_then(|v| v.to_str().ok());
let ok = matches!(range, Some(r) if r.starts_with("bytes ") && r.contains('/'));
if !ok { /* restart download from scratch, removing the .part file */ } Try / catch
match download().await {
Err(e) if e.to_string().contains("invalid Content-Range") => {
remove_partial_download();
download().await?; // fresh, non-resumed attempt
}
other => other?,
} Prevention
- Avoid resuming through proxies/CDNs known to mangle Content-Range headers.
- Clear stale .part files before retrying downloads through unusual networks.
- Test download servers with `curl -r 0-1 -D -` to confirm valid 206 + Content-Range.
When it happens
Trigger: Calling mise's HTTP download path (src/http.rs resume_download) against a server that responds 206 with a missing or unparseable Content-Range header, both on the initial resumed request and after the automatic restart-without-resume retry also returns a 206 whose Content-Range cannot be parsed.
Common situations: Downloading from a proxy, CDN, or misbehaving origin that emits 206 responses with non-standard or stripped Content-Range headers; middleboxes that mangle headers; caching proxies that return 206 from a stale entry.
Related errors
- should not be called for system tool
- HTTP download timed out after {} for {} (attempt {}, {} byte
- server returned inconsistent partial content
- Got HTML instead of text from {}
- cannot encode #{value.class} as JSON
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/1bf11274e91962ba.
Report an issue: GitHub.