tonhowtf/omniget · error

SponsorBlock: HTTP

Error message

SponsorBlock: HTTP {}

What it means

Thrown when the SponsorBlock API returns a non-OK (non-2xx) HTTP status to the segments query. The error embeds the response's status code so the caller can distinguish 404 (no video), 429 (rate limit), 5xx (server trouble), etc.

Solutions

  1. Read the embedded status code and handle 429 by waiting/backing off before retrying.
  2. Retry 5xx errors after a delay — they are usually transient server-side issues.
  3. Verify the categories list and request shape match the SponsorBlock API contract if status is 400.
  4. Check SponsorBlock service status (status.sponsor.ajay.app) during outages.
Defensive patterns

Strategy: retry

Try / catch

match sponsorblock::segments(&video, &cats).await {
    Ok(s) => use(s),
    Err(e) if e.to_string().contains("HTTP 429") => {
        tokio::time::sleep(Duration::from_secs(30)).await;
        // retry once
    }
    Err(e) => log::warn("sponsorblock unavailable: {e}"),
}

Prevention

When it happens

Trigger: Calling `sponsorblock::segments` when the SponsorBlock server replies with an error status: network/proxy issues surfacing as 5xx, per-account rate limiting (429), or an unexpected request the API rejects.

Common situations: Submitting queries too fast (SponsorBlock rate limits per user ID); SponsorBlock API downtime or maintenance; a proxy/firewall returning error pages; invalid categories parameter causing 400.

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


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/sponsorblock.rs:102

    let client = super::client()?;
    let resp = client.get(&url).send().await?;
    let mut segs: Vec<Segment> = Vec::new();
    if resp.status().as_u16() == 404 {
        // sem segmentos para esse prefixo
    } else if resp.status().is_success() {
        let arr: Vec<serde_json::Value> = resp.json().await?;
        for v in arr {
            if v["videoID"].as_str() == Some(id.as_str()) {
                if let Some(list) = v["segments"].as_array() {
                    segs.extend(
                        list.iter()
                            .filter_map(|s| serde_json::from_value(s.clone()).ok()),
                    );
                }
            }
        }
    } else {
        return Err(anyhow!("SponsorBlock: HTTP {}", resp.status()));
    }
    segs.sort_by(|a, b| {
        a.segment[0]
            .partial_cmp(&b.segment[0])
            .unwrap_or(std::cmp::Ordering::Equal)
    });
    let skipped: f64 = segs
        .iter()
        .filter(|s| s.action_type == "skip" || s.action_type.is_empty())
        .map(|s| (s.segment[1] - s.segment[0]).max(0.0))
        .sum();
    let mut used: Vec<&str> = segs
        .iter()
        .filter(|s| s.action_type != "chapter" && s.action_type != "poi")
        .map(|s| s.category.as_str())
        .collect();
    used.sort();
    used.dedup();

View on GitHub (pinned to 8600b91f42)