tonhowtf/omniget · error · anyhow::Error
HTTP downloading segment
Error message
HTTP {} downloading segment What it means
Raised in download_segment_with_retry when the segment response status is a non-success that is NOT treated as fatal: any 5xx server error, 429 rate limit, or 408 request timeout. Unlike the fatal branch, the caller's retry loop keeps retrying this segment with exponential backoff. The status code is included in the message.
Solutions
- Let the built-in retry with jittered backoff handle it; if it still fails, lower concurrent segment downloads to reduce 429s.
- Respect Retry-After headers on 429/503 responses when backing off.
- Retry the whole download later — 5xx are typically transient server-side issues.
- Use a different CDN mirror/edge or fallback rendition URL if the provider offers one.
Example fix
// before
return Err(anyhow::anyhow!("HTTP {} downloading segment", code));
// after
if code == 429 {
if let Some(ra) = resp.headers().get(reqwest::header::RETRY_AFTER).and_then(|v| v.to_str().ok()) {
let secs: u64 = ra.parse().unwrap_or(2);
tokio::time::sleep(std::time::Duration::from_secs(secs)).await;
}
}
return Err(anyhow::anyhow!("HTTP {} downloading segment {} (retryable)", code, seg_url)); Defensive patterns
Strategy: retry
Validate before calling
// classify status before deciding fate
let code = resp.status().as_u16();
let retryable = code >= 500 || code == 429 || code == 408;
if retryable {
if let Some(retry_after) = resp.headers().get("Retry-After").and_then(|v| v.to_str().ok()) {
let secs: u64 = retry_after.parse().unwrap_or(1);
tokio::time::sleep(std::time::Duration::from_secs(secs)).await;
}
} Try / catch
match result {
Err(e) if !e.to_string().contains("(fatal)") => {
// retryable: keep last_err and back off with jitter
last_err = Some(e);
tokio::time::sleep(jittered_backoff(attempt)).await;
}
Err(e) => return Err(e),
Ok(v) => return Ok(v),
} Prevention
- Cap concurrent segment downloads to avoid triggering 429 rate limits.
- Honor Retry-After headers instead of fixed backoff on 429/503.
- Use jittered exponential backoff so parallel workers don't hammer the CDN in lockstep.
- Configure a reasonable total time budget so transient 5xx storms don't stall the whole download.
When it happens
Trigger: Segment GET returns 500/502/503/504 from the CDN or origin, or 429 Too Many Requests / 408 Request Timeout. After exhausting retries the loop surfaces the last such error.
Common situations: CDN under load (502/503 from CloudFront/Akamai edge), server-side rate limiting (429) when downloading many parallel segments, origin timeouts (408/504) on slow storage backends, transient upstream failures during live events.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- HTTP fetching playlist
- Failed to download attachment
- HTTP (fatal) downloading segment
- Timeout downloading segment
- YouTube não retornou URL
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/9fdedff0bbe253d0.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/hls_downloader.rs:730
let mut last_err = None;
for attempt in 0..max_retries {
if cancel.is_cancelled() {
anyhow::bail!("Download cancelled");
}
let result = tokio::time::timeout(SEGMENT_TIMEOUT, async {
let resp = apply_referer_headers(client.get(url), referer)
.header("User-Agent", user_agent)
.send()
.await?;
let status = resp.status();
if !status.is_success() {
let code = status.as_u16();
if (400..500).contains(&code) && code != 429 && code != 408 {
return Err(anyhow::anyhow!("HTTP {} (fatal) downloading segment", code));
}
return Err(anyhow::anyhow!("HTTP {} downloading segment", code));
}
resp.bytes()
.await
.map(|b| b.to_vec())
.map_err(|e| anyhow::anyhow!(e))
})
.await;
match result {
Ok(Ok(data)) => return Ok(data),
Ok(Err(e)) => {
if e.to_string().contains("(fatal)") {
return Err(e);
}
last_err = Some(e);
}
Err(_) => last_err = Some(anyhow::anyhow!("Timeout downloading segment")),View on GitHub (pinned to 8600b91f42)