{"record":{"id":"175ac671b01b8ac6","repo":"tonhowtf/omniget","slug":"dois-trechos-se-sobrep-em-em-1-s","errorCode":null,"errorMessage":"dois trechos se sobrepõem em {:.1}s","messagePattern":"dois trechos se sobrepõem em (.+?)s","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/sponsorblock.rs","lineNumber":254,"sourceCode":"        if !pontual && s.end <= s.start {\n            return Err(anyhow!(\"trecho {}: o fim tem de vir depois do começo\", n));\n        }\n        if s.action_type == \"chapter\" && s.description.trim().is_empty() {\n            return Err(anyhow!(\"trecho {}: capítulo precisa de um título\", n));\n        }\n        if duration > 0.0 && s.end > duration + 1.0 {\n            return Err(anyhow!(\"trecho {}: passa do fim do vídeo\", n));\n        }\n    }\n    // Sobreposição só importa entre trechos que pulam pedaço.\n    let mut cortes: Vec<&NewSegment> = segments\n        .iter()\n        .filter(|s| s.action_type == \"skip\" || s.action_type == \"mute\")\n        .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    }","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/sponsorblock.rs#L236-L272","documentation":"validate_segments collects all skip/mute segments, sorts them by start, and rejects any adjacent pair where the next segment starts before the previous one ends — i.e. two cut segments overlap, and the overlap would be skipped twice. The error reports the start time of the second segment and the overlap size in seconds.","triggerScenarios":"Calling build_payload/submit with two or more segments of type \"skip\" or \"mute\" whose time ranges intersect, e.g. [10.0–30.0] and [25.0–40.0].","commonSituations":"Users adding overlapping 'skip sponsor' and 'skip self-promo' sections over the same part of a video; importing segments from another tool that allowed overlaps; merging segment lists by concatenation instead of by time.","solutions":["Adjust the segment boundaries so skip/mute ranges do not overlap (e.g. end the first at 25.0 or start the second at 30.0).","Merge overlapping segments into one before calling build_payload.","Keep at most one skip/mute segment covering any given time range.","Note only skip/mute are checked — overlapping chapters/poi entries are fine; reclassify one segment if overlap is intended."],"exampleFix":"// before\nsegments: [ {\"skip\", 10.0, 30.0}, {\"mute\", 25.0, 40.0} ]\n// after\nsegments: [ {\"skip\", 10.0, 25.0}, {\"mute\", 25.0, 40.0} ]","handlingStrategy":"validation","validationCode":"fn no_overlapping_cuts(segments: &[NewSegment]) -> bool {\n    let mut c: Vec<_> = segments.iter().filter(|s| matches!(s.action_type.as_str(), \"skip\" | \"mute\")).collect();\n    c.sort_by(|a, b| a.start.total_cmp(&b.start));\n    c.windows(2).all(|w| w[1].start >= w[0].end)\n}","typeGuard":"fn overlaps(a: &NewSegment, b: &NewSegment) -> bool {\n    matches!(a.action_type.as_str(), \"skip\" | \"mute\") && matches!(b.action_type.as_str(), \"skip\" | \"mute\") && b.start < a.end\n}","tryCatchPattern":"match build_payload(&id, &user, dur, &segs) {\n    Err(e) if e.to_string().contains(\"se sobrepõem\") => open_overlap_editor()?,\n    other => other?,\n}","preventionTips":["Merge or split overlapping skip/mute segments before submitting.","Show existing segments on a timeline in the UI so overlaps are visible.","Deduplicate and sort segments when importing from external tools."],"tags":["validation","sponsorblock","rust","overlap"],"backgroundTag":"conflicting-config-options","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"}