{"record":{"id":"c456b9c0167a221b","repo":"tonhowtf/omniget","slug":"sponsorblock","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/sponsorblock.rs","lineNumber":358,"sourceCode":"        return Err(anyhow!(\n            \"o envio é público e vale para todo mundo: confirme antes\"\n        ));\n    }\n    let id = video_id(&opts.url)\n        .ok_or_else(|| anyhow!(\"nao reconheci um video do YouTube em: {}\", opts.url))?;\n    let user = local_user_id()?;\n    let body = build_payload(&id, &user, opts.video_duration, &opts.segments)?;\n\n    let client = super::client()?;\n    let resp = client\n        .post(format!(\"{}/api/skipSegments\", SERVER))\n        .json(&body)\n        .send()\n        .await?;\n    let status = resp.status().as_u16();\n    let text = resp.text().await.unwrap_or_default();\n    if !(200..300).contains(&status) {\n        return Err(anyhow!(\"{}\", submit_error(status, &text)));\n    }\n    let uuids: Vec<String> = serde_json::from_str::<Vec<serde_json::Value>>(&text)\n        .map(|arr| {\n            arr.iter()\n                .filter_map(|v| v[\"UUID\"].as_str().map(|s| s.to_string()))\n                .collect()\n        })\n        .unwrap_or_default();\n    Ok(SubmitResult {\n        accepted: if uuids.is_empty() {\n            opts.segments.len()\n        } else {\n            uuids.len()\n        },\n        video_id: id,\n        uuids,\n        fingerprint: public_fingerprint(&user),\n        message: text.trim().chars().take(200).collect(),","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/sponsorblock.rs#L340-L376","documentation":"After POSTing the payload to the SponsorBlock /api/skipSegments endpoint, submit checks the HTTP status; any response outside 200..300 is converted into an anyhow error whose message comes from submit_error(status, &text) — a mapped, human-readable description of the API error (or a generic 'SponsorBlock: HTTP <status>' fallback). This is the propagation point for all server-side rejections.","triggerScenarios":"The SponsorBlock server returns 400 (invalid payload), 403 (banned user), 409/429 (duplicate segment / rate limit), 5xx (server trouble), or any other non-2xx status on submit.","commonSituations":"Submitting a segment that already exists (duplicate); the user's private ID being banned/downvoted; SponsorBlock rate limiting rapid submissions; network proxies or captive portals returning HTML error pages; SponsorBlock API outages.","solutions":["Read the error message: it contains submit_error's mapping of the status and the first part of the response body — fix the indicated cause.","For 409, the segment already exists — no resubmission needed.","For 429, wait and retry with backoff; reduce submission frequency.","For 403, the local user ID is banned — regenerate the key or appeal via SponsorBlock.","For 5xx or network errors, retry later; check the SponsorBlock service status."],"exampleFix":"// before\nlet resp = client.post(url).json(&body).send().await?; // 429 ignored until here\n// after\nif status == 429 {\n    tokio::time::sleep(Duration::from_secs(30)).await;\n    return submit(opts).await; // retry with backoff\n}","handlingStrategy":"retry","validationCode":"// pre-flight: check connectivity\nlet resp = client.get(format!(\"{SERVER}/api/status\")).send().await?;","typeGuard":null,"tryCatchPattern":"match submit(opts.clone()).await {\n    Err(e) if e.to_string().contains(\"HTTP 429\") => { sleep(BACKOFF).await; submit(opts).await }\n    Err(e) if e.to_string().contains(\"HTTP 409\") => Ok(SubmitResult::duplicate()), // already exists\n    other => other,\n}","preventionTips":["Match on the status embedded in the error message to handle 409 (duplicate) and 429 (rate limit) distinctly.","Add exponential backoff for 5xx and 429 responses.","Avoid duplicate submissions by tracking already-submitted segments locally.","Check SponsorBlock service status before bulk submissions."],"tags":["sponsorblock","http","api","rust","network"],"backgroundTag":"api-error-response","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}