tonhowtf/omniget · error · anyhow::Error

incomplete segment: of bytes

Error message

incomplete segment: {} of {} bytes

What it means

After the stream ends (or the ceiling is reached), download_segment verifies the number of bytes currently downloaded for the segment equals its current target. If fewer bytes were written than required, the segment is declared incomplete so the worker retries it instead of assembling a corrupt file.

Solutions

  1. Retry the segment — a fresh ranged GET resumes at the written offset
  2. Compare Content-Length/Content-Range with the requested range to detect server-side truncation
  3. Check disk space and file-descriptor limits if truncation is local (though this path is server-side)
  4. If a specific server always truncates, exclude it or use single-stream download
Defensive patterns

Strategy: retry

Validate before calling

// compare advertised size with requested range before trusting a segment
let head = client.head(url).send().await?;
let len: u64 = head.headers().get("content-length")
    .and_then(|v| v.to_str().ok()).and_then(|s| s.parse().ok()).unwrap_or(0);
if len == 0 { eprintln!("unknown size; segmented integrity check unreliable"); }

Try / catch

if let Err(e) = download_segment(&seg, &cancel).await {
    if e.to_string().contains("incomplete segment") {
        tracing::warn!("segment truncated by server; retrying from offset");
        download_segment(&seg, &cancel).await?;
    } else { return Err(e.into()); }
}

Prevention

When it happens

Trigger: Stream ended (eof or 'ceiling shrank') with written bytes < (end_ceiling+1 - range_start); e.g. server closed the connection early after a partial body, or the stop_reason logic exited before reaching target.

Common situations: Origin truncating large files; Content-Length shorter than Range requested; connection drop that reqwest surfaces as clean EOF; misconfigured server clamping ranges.

Related errors


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

Appendix: source

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

                    written
                );
                return Err(anyhow!("read timed out after {:?}", cfg.read_timeout));
            }
        }
    }
    file.flush().await?;
    let cur_end = seg.end_ceiling.load(Ordering::Relaxed);
    let cur_target = (cur_end - begin) + 1;
    let cur_dl = seg.downloaded.load(Ordering::Relaxed);
    tracing::debug!(
        "[http_fetcher] segment {}: {} bytes in {:.2}s ({})",
        seg.id,
        written,
        started.elapsed().as_secs_f64(),
        stop_reason
    );
    if cur_dl < cur_target {
        return Err(anyhow!(
            "incomplete segment: {} of {} bytes",
            cur_dl,
            cur_target
        ));
    }
    Ok(())
}

fn is_fatal(err: &anyhow::Error) -> bool {
    let m = err.to_string();
    for code in &[
        "HTTP 400", "HTTP 401", "HTTP 403", "HTTP 404", "HTTP 405", "HTTP 410", "HTTP 451",
    ] {
        if m.contains(code) {
            return true;
        }
    }
    if m.contains("HTML instead of media") {

View on GitHub (pinned to 8600b91f42)