{"record":{"id":"a83d2140c6abd3c9","repo":"tonhowtf/omniget","slug":"n-o-reconheci-o-v-deo-do-youtube","errorCode":null,"errorMessage":"não reconheci o vídeo do YouTube","messagePattern":"não reconheci o vídeo do YouTube","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/sponsorblock.rs","lineNumber":268,"sourceCode":"        .collect();\n    cortes.sort_by(|a, b| a.start.total_cmp(&b.start));\n    for par in cortes.windows(2) {\n        if par[1].start < par[0].end {\n            return Err(anyhow!(\"dois trechos se sobrepõem em {:.1}s\", par[1].start));\n        }\n    }\n    Ok(())\n}\n\n/// O corpo exato do `POST /api/skipSegments`.\npub fn build_payload(\n    video_id: &str,\n    user_id: &str,\n    duration: f64,\n    segments: &[NewSegment],\n) -> anyhow::Result<serde_json::Value> {\n    if video_id.len() != 11 {\n        return Err(anyhow!(\"não reconheci o vídeo do YouTube\"));\n    }\n    if user_id.trim().len() < 30 {\n        return Err(anyhow!(\"a chave local do SponsorBlock está corrompida\"));\n    }\n    validate_segments(segments, duration)?;\n    let segs: Vec<serde_json::Value> = segments\n        .iter()\n        .map(|s| {\n            let mut o = serde_json::json!({\n                \"segment\": [s.start, s.end],\n                \"category\": s.category,\n                \"actionType\": s.action_type,\n            });\n            if !s.description.trim().is_empty() {\n                o[\"description\"] = serde_json::Value::String(s.description.trim().to_string());\n            }\n            o\n        })","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/sponsorblock.rs#L250-L286","documentation":"build_payload validates that the video ID string is exactly 11 characters, the canonical length of a YouTube video ID, before constructing the POST /api/skipSegments body. Anything else is rejected early so a malformed ID never reaches SponsorBlock.","triggerScenarios":"Passing a full URL, an 11+-character string with extra characters, a shortened youtu.be path, or an empty string as the video_id argument to build_payload (or as the ID resolved from submit's url).","commonSituations":"Extracting the ID with a regex that also captures query parameters (&t=90s); passing the whole watch?v= URL instead of the v parameter; IDs from oEmbed/short links with padding or whitespace.","solutions":["Extract just the 11-character ID (e.g. from the v= query parameter or youtu.be path) before calling build_payload.","Reuse the library's own video_id(&url) helper (as submit does) instead of manual parsing.","Trim whitespace and strip query strings from the ID string.","Log the ID and its length on failure; note this error is raised by build_payload, whereas submit raises the distinct 'nao reconheci um video do YouTube em: {}' message."],"exampleFix":"// before\nlet id = \"https://youtu.be/dQw4w9WgXcQ?t=1\"; // 27 chars\n// after\nlet id = video_id(url).ok_or_else(|| anyhow!(\"URL inválida\"))?; // \"dQw4w9WgXcQ\"","handlingStrategy":"validation","validationCode":"fn is_youtube_id(id: &str) -> bool {\n    id.len() == 11 && id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')\n}","typeGuard":"fn as_video_id(s: &str) -> Option<&str> {\n    (s.len() == 11).then_some(s)\n}","tryCatchPattern":"match build_payload(&id, &user, dur, &segs) {\n    Err(e) if e.to_string().contains(\"não reconheci o vídeo\") => eprintln!(\"ID inválido: {:?} (len={})\", id, id.len()),\n    other => other?,\n}","preventionTips":["Extract the ID with the library's video_id() helper instead of manual string slicing.","Strip query strings and whitespace from IDs before use.","Assert id.len() == 11 in tests that build payloads."],"tags":["validation","sponsorblock","youtube","rust","video-id"],"backgroundTag":"invalid-identifier-format","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"}