{"record":{"id":"0f5cea627880d2e5","repo":"tonhowtf/omniget","slug":"sponsorblock-http","errorCode":null,"errorMessage":"SponsorBlock: HTTP {}","messagePattern":"SponsorBlock: HTTP (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/sponsorblock.rs","lineNumber":102,"sourceCode":"    let client = super::client()?;\n    let resp = client.get(&url).send().await?;\n    let mut segs: Vec<Segment> = Vec::new();\n    if resp.status().as_u16() == 404 {\n        // sem segmentos para esse prefixo\n    } else if resp.status().is_success() {\n        let arr: Vec<serde_json::Value> = resp.json().await?;\n        for v in arr {\n            if v[\"videoID\"].as_str() == Some(id.as_str()) {\n                if let Some(list) = v[\"segments\"].as_array() {\n                    segs.extend(\n                        list.iter()\n                            .filter_map(|s| serde_json::from_value(s.clone()).ok()),\n                    );\n                }\n            }\n        }\n    } else {\n        return Err(anyhow!(\"SponsorBlock: HTTP {}\", resp.status()));\n    }\n    segs.sort_by(|a, b| {\n        a.segment[0]\n            .partial_cmp(&b.segment[0])\n            .unwrap_or(std::cmp::Ordering::Equal)\n    });\n    let skipped: f64 = segs\n        .iter()\n        .filter(|s| s.action_type == \"skip\" || s.action_type.is_empty())\n        .map(|s| (s.segment[1] - s.segment[0]).max(0.0))\n        .sum();\n    let mut used: Vec<&str> = segs\n        .iter()\n        .filter(|s| s.action_type != \"chapter\" && s.action_type != \"poi\")\n        .map(|s| s.category.as_str())\n        .collect();\n    used.sort();\n    used.dedup();","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/sponsorblock.rs#L84-L120","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the embedded status code and handle 429 by waiting/backing off before retrying.","Retry 5xx errors after a delay — they are usually transient server-side issues.","Verify the categories list and request shape match the SponsorBlock API contract if status is 400.","Check SponsorBlock service status (status.sponsor.ajay.app) during outages."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match sponsorblock::segments(&video, &cats).await {\n    Ok(s) => use(s),\n    Err(e) if e.to_string().contains(\"HTTP 429\") => {\n        tokio::time::sleep(Duration::from_secs(30)).await;\n        // retry once\n    }\n    Err(e) => log::warn(\"sponsorblock unavailable: {e}\"),\n}","preventionTips":["Back off on 429 — SponsorBlock rate limits per user ID.","Treat 5xx as transient and retry with delay.","Check SponsorBlock status page during outages.","Cache segment results per video to reduce request volume."],"tags":["http","sponsorblock","api"],"backgroundTag":"http-error-response","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}