{"record":{"id":"c5848440a5d4e2b1","repo":"tonhowtf/omniget","slug":"server-did-not-honor-range-http-200","errorCode":null,"errorMessage":"server did not honor Range (HTTP 200)","messagePattern":"server did not honor Range \\(HTTP 200\\)","errorType":"http","errorClass":"anyhow::Error","httpStatus":200,"severity":"error","filePath":"src-tauri/omniget-core/src/core/http_fetcher.rs","lineNumber":969,"sourceCode":"    let range_start = begin + already;\n\n    let mut req = client.get(url);\n    if let Some(h) = headers {\n        req = req.headers(headers_without_range(h));\n    }\n    req = req.header(\n        reqwest::header::RANGE,\n        format!(\"bytes={}-{}\", range_start, end),\n    );\n\n    let resp = tokio::time::timeout(cfg.connect_timeout, req.send())\n        .await\n        .map_err(|_| anyhow!(\"connect timeout\"))??;\n\n    let status = resp.status();\n    if status != reqwest::StatusCode::PARTIAL_CONTENT {\n        if status.is_success() {\n            return Err(anyhow!(\"server did not honor Range (HTTP 200)\"));\n        }\n        return Err(anyhow!(\"HTTP {}\", status));\n    }\n\n    // A 206 alone is not proof the server gave us the slice we asked for. If it\n    // answers a different offset and we write the body at ours anyway, the file\n    // still ends up the right size and is silently corrupt — the one failure\n    // mode a segmented download cannot detect later.\n    if let Some(start) = content_range_start(resp.headers()) {\n        if start != range_start {\n            return Err(anyhow!(\n                \"server answered range at byte {} but {} was requested\",\n                start,\n                range_start\n            ));\n        }\n    }\n","sourceCodeStart":951,"sourceCodeEnd":987,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/http_fetcher.rs#L951-L987","documentation":"Chunked download depends on the server honoring Range requests. If the segment GET answers 200 instead of 206 PARTIAL_CONTENT, the server sent the whole body and ignored the Range header; writing it at the segment's offset would corrupt the assembled file, so download_segment refuses. This guards the core assumption of multi-segment downloading.","triggerScenarios":"Server (or an intermediate cache/CDN) responds HTTP 200 to a bytes=start-end GET — either it does not support ranges at all, or it strips/ignores the Range header — while status.is_success() is true.","commonSituations":"CDNs or reverse proxies configured with ignore Range, dynamic CGI/PHP endpoints that ignore headers, misconfigured caching layers, or servers that only support ranges on static files.","solutions":["Fall back to single-stream (non-chunked) download for this URL; the server cannot serve segments.","Check whether a proxy/CDN in front of the origin strips Range and fix its configuration (e.g. proxy_cache_bypass, respect Range headers).","Verify with `curl -v -r 0-99 -o /dev/null <url>` — a compliant server answers 206 with Content-Range.","Serve the file from a host known to support byte ranges (static file servers, S3, nginx)."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// capability pre-check before chunked download\nlet head = client.head(url).send().await?;\nlet accepts_ranges = head\n    .headers()\n    .get(reqwest::header::ACCEPT_RANGES)\n    .and_then(|v| v.to_str().ok())\n    .map(|v| v == \"bytes\")\n    .unwrap_or(false);\nlet strategy = if accepts_ranges { Chunked } else { SingleStream };","typeGuard":null,"tryCatchPattern":"match download_chunked(...).await {\n    Err(e) if e.to_string().contains(\"did not honor Range\") => {\n        download_single_stream(...).await?; // graceful fallback\n    }\n    other => { other?; }\n}","preventionTips":["Check the Accept-Ranges header during probe and select the download strategy from it.","Verify a live 206 with a curl -r smoke test against new download hosts.","Audit CDN/proxy configs for Range-stripping settings.","Keep a single-stream fallback path in every download pipeline."],"tags":["http","range-requests","download","protocol"],"backgroundTag":"unexpected-http-status","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}