tonhowtf/omniget · error · anyhow::Error

server did not honor Range (HTTP 200)

Error message

server did not honor Range (HTTP 200)

What it means

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.

Solutions

  1. Fall back to single-stream (non-chunked) download for this URL; the server cannot serve segments.
  2. Check whether a proxy/CDN in front of the origin strips Range and fix its configuration (e.g. proxy_cache_bypass, respect Range headers).
  3. Verify with `curl -v -r 0-99 -o /dev/null <url>` — a compliant server answers 206 with Content-Range.
  4. Serve the file from a host known to support byte ranges (static file servers, S3, nginx).
Defensive patterns

Strategy: fallback

Validate before calling

// capability pre-check before chunked download
let head = client.head(url).send().await?;
let accepts_ranges = head
    .headers()
    .get(reqwest::header::ACCEPT_RANGES)
    .and_then(|v| v.to_str().ok())
    .map(|v| v == "bytes")
    .unwrap_or(false);
let strategy = if accepts_ranges { Chunked } else { SingleStream };

Try / catch

match download_chunked(...).await {
    Err(e) if e.to_string().contains("did not honor Range") => {
        download_single_stream(...).await?; // graceful fallback
    }
    other => { other?; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/c5848440a5d4e2b1. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/http_fetcher.rs:969

    let range_start = begin + already;

    let mut req = client.get(url);
    if let Some(h) = headers {
        req = req.headers(headers_without_range(h));
    }
    req = req.header(
        reqwest::header::RANGE,
        format!("bytes={}-{}", range_start, end),
    );

    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
            ));
        }
    }

View on GitHub (pinned to 8600b91f42)