{"record":{"id":"d2eb51ec65b389ea","repo":"ducaale/xh","slug":"content-range-has-wrong-start","errorCode":null,"errorMessage":"Content-Range has wrong start: {:?}","messagePattern":"Content-Range has wrong start: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/download.rs","lineNumber":154,"sourceCode":"                .parse()\n                .context(\"Can't parse Content-Range complete_length\")\n        })\n        .transpose()?;\n    // Note that last_byte_pos must be strictly less than complete_length\n    // If first_byte_pos == last_byte_pos exactly one byte is sent\n    if first_byte_pos > last_byte_pos {\n        return Err(anyhow!(\"Invalid Content-Range: {:?}\", header));\n    }\n    if let Some(complete_length) = complete_length {\n        if last_byte_pos >= complete_length {\n            return Err(anyhow!(\"Invalid Content-Range: {:?}\", header));\n        }\n        if complete_length != last_byte_pos + 1 {\n            return Err(anyhow!(\"Content-Range has wrong end: {:?}\", header));\n        }\n    }\n    if expected_start != first_byte_pos {\n        return Err(anyhow!(\"Content-Range has wrong start: {:?}\", header));\n    }\n    Ok(last_byte_pos + 1)\n}\n\nconst BAR_TEMPLATE: &str =\n    \"{spinner:.green} {percent}% [{wide_bar:.cyan/blue}] {bytes} {bytes_per_sec} ETA {eta}\";\nconst UNCOLORED_BAR_TEMPLATE: &str =\n    \"{spinner} {percent}% [{wide_bar}] {bytes} {bytes_per_sec} ETA {eta}\";\nconst SPINNER_TEMPLATE: &str = \"{spinner:.green} {bytes} {bytes_per_sec} {wide_msg}\";\nconst UNCOLORED_SPINNER_TEMPLATE: &str = \"{spinner} {bytes} {bytes_per_sec} {wide_msg}\";\n\npub fn download_file(\n    response: Response,\n    file_name: Option<PathBuf>,\n    // If we fall back on taking the filename from the URL it has to be the\n    // original URL, before redirects. That's less surprising and matches\n    // HTTPie. Hence this argument.\n    orig_url: &reqwest::Url,","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/ducaale/xh/blob/2404aceecc08b0b2d100fedc96f57745cd5904dc/src/download.rs#L136-L172","documentation":"total_for_content_range validates a Content-Range header returned for a resumed download. After parsing the byte range and total, it checks that the first byte position matches the resume offset the client requested. A mismatch means the server did not resume the transfer from the expected offset.","triggerScenarios":"download_file called with a resume offset (Some(resume)) where the server's Content-Range header starts at a byte position different from the requested offset (expected_start != first_byte_pos), e.g. after a 206 Partial Content response reflecting a different range.","commonSituations":"Resume offset stored in a stale .partial metadata file no longer matches server-side file state; server rewrites or truncates the resource between retries; a proxy returns a different range than requested; resuming against a server that regenerated dynamic content.","solutions":["Delete the partial download file and its resume offset metadata, then restart the download from byte 0.","Verify the resource URL/ETag is unchanged between the original request and the resume request (add If-Range).","Check whether a proxy or CDN is altering range requests; bypass it or disable resume.","Re-request the range explicitly with the correct Range header matching the stored offset."],"exampleFix":"// before\n// resume with stale offset\nlet resume = stale_offset;\n// after\nlet resume = if head_etag == saved_etag { saved_offset } else { 0 };","handlingStrategy":"validation","validationCode":"let head = client.head(url).send()?;\nlet etag = head.headers().get(header::ETAG).cloned();\nlet ok = etag.as_deref() == saved_etag.as_deref();\nlet resume_offset = if ok { saved_offset } else { 0 };","typeGuard":"fn content_range_matches(header: &str, expected_start: u64) -> bool {\n    header\n        .strip_prefix(\"bytes \")\n        .and_then(|r| r.split('-').next())\n        .and_then(|s| s.parse::<u64>().ok())\n        .map_or(false, |start| start == expected_start)\n}","tryCatchPattern":null,"preventionTips":["Always send If-Range with the ETag/Last-Modified so the server refuses stale resumes.","Store the offset together with the ETag of the original response.","Delete partial state when the remote resource changes.","Fall back to a fresh download when resume validation fails."],"tags":["download","http","resume","content-range"],"backgroundTag":"unexpected-response-shape","analyzedSha":"2404aceecc08b0b2d100fedc96f57745cd5904dc","analyzedAt":"2026-09-13T19:13:33.814Z","contentChangedAt":"2026-09-13T19:13:33.814Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}