jdx/mise · error
server returned an invalid Content-Range response
Error message
server returned an invalid Content-Range response
What it means
On resume, mise sends a Range request and expects a valid bytes-based Content-Range header describing the returned slice. If the header is missing, malformed, or a non-bytes unit (e.g. */total), and a previous no-resume restart already occurred, it bails with this error after clearing the partial.
Solutions
- Bypass/fix the proxy or server middleware so Range responses include a valid 'Content-Range: bytes start-end/total' header.
- Clear the partial download and retry from scratch (or from a different mirror).
- If the resume offset is beyond the file size (server returns */total), remove the stale partial so the next request starts fresh.
Defensive patterns
Strategy: validation
Validate before calling
curl -fsSI -H 'Range: bytes=10-19' "$url" | grep -i '^content-range: bytes ' || echo "invalid/missing Content-Range"
Prevention
- Confirm the download source returns 'Content-Range: bytes start-end/total' on 206s
- Clear stale partials whose offset may exceed the current file size
- Avoid proxies that strip or rewrite response headers
When it happens
Trigger: A resumed download where the server's 206 response lacks a parseable bytes Content-Range (missing header, 'Content-Range: bytes */N' for unsatisfied ranges, or garbage syntax) and the retry-without-resume path also failed the same way.
Common situations: Server or proxy that supports 206 but omits/mangles Content-Range; range requests answered by a cache layer with inconsistent headers; servers responding to out-of-range resumes with the unparseable 'bytes */total' form.
Related errors
- server returned partial content without a resumable request
- download cancelled by user
- HTTP download timed out after
- server returned inconsistent partial content
- should not be called for system tool
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/1bf11274e91962ba.
Report an issue: GitHub.
Appendix: source
Thrown at src/http.rs:1151
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 533346cc37)