tonhowtf/omniget · error · anyhow::Error
server answered range at byte
Error message
server answered range at byte {} but {} was requested What it means
Even with a 206 response, download_segment validates the Content-Range start offset against the requested range_start. A 206 for a different offset would be written at the wrong file position, producing a right-sized but corrupt file, so the mismatch is rejected.
Solutions
- Inspect the Content-Range header returned by the server for the exact Range request sent
- Disable or bypass caching layers/CDN transforms for range requests
- Drop and rebuild any persistent connection pools after noticing stale offsets
- Retry the segment with a fresh connection; if the server keeps mis-slicing, fall back to single-stream download
Example fix
// request: Range: bytes=100-199 // response: Content-Range: bytes 200-299/1000 -> error // fix: verify server honors exact offsets curl -sD - -o /dev/null -H "Range: bytes=100-199" https://example.com/file.bin | grep Content-Range
Defensive patterns
Strategy: validation
Validate before calling
// verify exact offset honoring before trusting the server
let r = client.get(url).header("Range", "bytes=100-199").send().await?;
let cr = r.headers().get("content-range").and_then(|v| v.to_str().ok()).unwrap_or("");
if !cr.starts_with("bytes 100-") { eprintln!("server rewrites ranges; disable segmentation"); } Type guard
fn content_range_matches(hdr: Option<&reqwest::header::HeaderValue>, want: u64) -> bool {
hdr.and_then(|h| h.to_str().ok())
.and_then(|s| s.strip_prefix("bytes "))
.and_then(|s| s.split('-').next())
.and_then(|s| s.parse::<u64>().ok())
.map(|start| start == want)
.unwrap_or(false)
} Try / catch
if let Err(e) = segment.download().await {
if e.to_string().contains("answered range at byte") {
tracing::warn!("server mis-slices ranges; restarting segment on new connection");
segment.download_fresh_connection().await?;
} else { return Err(e); }
} Prevention
- Validate a server's Content-Range behavior once and cache the result
- Avoid caching proxies/CDN transforms for range requests
- Use fresh connections when resuming segments
- Add integrity checks (hash) for assembled files
When it happens
Trigger: Server returns 206 whose Content-Range start differs from the requested range_start, e.g. answering bytes=200- instead of the requested bytes=100-, or resuming from a cached/stale offset.
Common situations: Misbehaving CDNs or caching layers that rewrite Content-Range; servers that normalize or clamp the requested range; buggy origin scripts computing their own offsets.
Related errors
- HTTP
- incomplete segment: of bytes
- server did not honor Range (HTTP 200)
- a API do TikTok respondeu HTTP
- Access denied (403). The video may be private or…
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/77dcfb5237419003.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/http_fetcher.rs:980
let resp = tokio::time::timeout(cfg.connect_timeout, req.send())
.await
.map_err(|_| anyhow!("connect timeout"))??;
let status = resp.status();
if status != reqwest::StatusCode::PARTIAL_CONTENT {
if status.is_success() {
return Err(anyhow!("server did not honor Range (HTTP 200)"));
}
return Err(anyhow!("HTTP {}", status));
}
// A 206 alone is not proof the server gave us the slice we asked for. If it
// answers a different offset and we write the body at ours anyway, the file
// still ends up the right size and is silently corrupt — the one failure
// mode a segmented download cannot detect later.
if let Some(start) = content_range_start(resp.headers()) {
if start != range_start {
return Err(anyhow!(
"server answered range at byte {} but {} was requested",
start,
range_start
));
}
}
if let Some(ct) = resp.headers().get(reqwest::header::CONTENT_TYPE) {
if let Ok(s) = ct.to_str() {
if s.contains("text/html") {
return Err(anyhow!("server returned HTML instead of media"));
}
}
}
let mut file = tokio::fs::OpenOptions::new()
.write(true)
.open(part_path)View on GitHub (pinned to 8600b91f42)