{"record":{"id":"cb4ba62a499850a7","repo":"ducaale/xh","slug":"content-range-has-wrong-end","errorCode":null,"errorMessage":"Content-Range has wrong end: {:?}","messagePattern":"Content-Range has wrong end: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/download.rs","lineNumber":150,"sourceCode":"    let complete_length: Option<u64> = caps\n        .name(\"complete_length\")\n        .map(|num| {\n            num.as_str()\n                .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>,","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/ducaale/xh/blob/2404aceecc08b0b2d100fedc96f57745cd5904dc/src/download.rs#L132-L168","documentation":"For a complete (non-wildcard) Content-Range, the declared complete_length must be exactly last_byte_pos + 1 — the range must end at the total. If it doesn't (and the range is otherwise positive), the header claims an inconsistent end and the resume is aborted.","triggerScenarios":"Server sends 'bytes 0-99/200' — a complete_length that doesn't match last_byte_pos + 1 (should be /100 for a full body, or use 'bytes 0-99/*' for a partial total).","commonSituations":"Servers that report the total of a different resource version than the range, proxies synthesizing ranges, resume attempts against files that changed size on the server.","solutions":["Delete the partial file and restart the download from scratch","Confirm the file hasn't changed on the server between the initial request and the resume (retry with a fresh ETag/size)","If the server intentionally sends partial totals, it should use the wildcard form 'bytes <start>-<end>/*'"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"fn content_range_end_consistent(last: u64, complete_length: Option<u64>) -> bool {\n    match complete_length {\n        None => true,\n        Some(cl) => cl == last + 1 || cl == 0, // wildcard handled elsewhere\n    }\n}","typeGuard":null,"tryCatchPattern":"match total_for_content_range(header, expected_start) {\n    Ok(total) => resume_from(expected_start, total),\n    Err(e) if e.to_string().contains(\"wrong end\") => {\n        eprintln!(\"Content-Range end mismatch (file may have changed); restarting\");\n        delete_partial_and_restart();\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["For partial totals the server should emit 'bytes <start>-<end>/*'","Check that the remote file size/ETag is unchanged before resuming","Treat wrong-end responses as a signal to discard the partial file"],"tags":["http","download","content-range","validation","rust"],"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"}