{"record":{"id":"4b1be733b03966ff","repo":"jdx/mise","slug":"server-returned-partial-content-without-a-resumabl","errorCode":null,"errorMessage":"server returned partial content without a resumable request","messagePattern":"server returned partial content without a resumable request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/http.rs","lineNumber":1013,"sourceCode":"                    debug!(\"range request at offset {offset} was unsatisfied for {total} bytes\");\n                }\n                partial.clear()?;\n                if offset > 0 && !restarted_without_resume {\n                    restarted_without_resume = true;\n                    continue;\n                }\n                resp.error_for_status_ref()?;\n            }\n\n            let (write_offset, total_size, validator, resumable, effective_filename) =\n                if resp.status() == StatusCode::PARTIAL_CONTENT {\n                    let Some((state, _)) = resume else {\n                        partial.clear()?;\n                        if !restarted_without_resume {\n                            restarted_without_resume = true;\n                            continue;\n                        }\n                        bail!(\"server returned partial content without a resumable request\");\n                    };\n                    let content_range = resp\n                        .headers()\n                        .get(CONTENT_RANGE)\n                        .and_then(|value| value.to_str().ok())\n                        .and_then(parse_content_range);\n                    let Some(ParsedContentRange::Bytes { start, end, total }) = content_range\n                    else {\n                        partial.clear()?;\n                        if restarted_without_resume {\n                            bail!(\"server returned an invalid Content-Range response\");\n                        }\n                        restarted_without_resume = true;\n                        continue;\n                    };\n                    let validator = response_validator(resp.headers());\n                    let response_length_matches = resp\n                        .content_length()","sourceCodeStart":995,"sourceCodeEnd":1031,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/http.rs#L995-L1031","documentation":"During a download, if the server responds with 206 Partial Content but the request was not a resumable (Range) request — there is no resume state to reconcile — mise clears the partial and retries once without resume. If it still receives a partial body without resumable state, it throws this error because it cannot account for the missing bytes.","triggerScenarios":"Server returns HTTP 206 Partial Content in response to a non-Range (or non-resumable) request, twice — including after the retry without resume. Also triggered by a buggy proxy/CDN that replies 206 incorrectly.","commonSituations":"Misbehaving reverse proxy or CDN mangling requests/ranges; server with broken HTTP range support replying 206 unconditionally; an aggressive caching proxy in a corporate network stripping Range headers but still answering 206.","solutions":["Retry the download; if it persists, bypass the proxy/mirror (unset *_MIRROR override, try the official URL directly)","Check intermediary proxies/CDNs that strip Range headers or emit spurious 206 responses and fix or avoid them","Report the server's incorrect 206 behavior to the mirror operator; meanwhile install via a different mirror","Update mise in case a newer version hardened handling of such servers"],"exampleFix":"# shell\n# before\nexport MISE_NODE_MIRROR='https://broken-mirror.example.com/node'\n# after (use official mirror)\nunset MISE_NODE_MIRROR","handlingStrategy":"retry","validationCode":"// probe that the mirror honors Range correctly before large installs\nlet resp = reqwest::Client::new().get(url)\n    .header(reqwest::header::RANGE, \"bytes=0-0\").send().await?;\nassert!(resp.status().is_success() || resp.status() == 416, \"bad mirror range behavior: {}\", resp.status());","typeGuard":null,"tryCatchPattern":"match download(url, dest).await {\n    Err(e) if e.to_string().contains(\"partial content without a resumable request\") => {\n        eprintln!(\"mirror misbehaving; falling back to official URL\");\n        download(official_url, dest).await?\n    }\n    other => other?,\n}","preventionTips":["Avoid mirrors/proxies that strip Range headers or reply 206 spuriously","Retry once on transient proxy faults, then switch mirrors","Keep mise updated for hardened HTTP download handling"],"tags":["http","download","range","protocol"],"backgroundTag":"unexpected-http-status","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}