tonhowtf/omniget · error

trecho : tempo inválido

Error message

trecho {}: tempo inválido

What it means

Numeric sanity check in `validate_segments`: start and end must both be finite (not NaN/inf) and non-negative. Invalid numbers are rejected locally with the 1-based segment index before a rate-limited submission is spent.

Solutions

  1. Ensure start/end are finite non-negative numbers before constructing NewSegment.
  2. Treat empty timestamp inputs as an error in the UI rather than letting NaN through.
  3. Use checked parsing (e.g. str::parse::<f64>() with error handling) instead of defaulting to NaN.
  4. Clamp or reject negative values at the segment-creation site.

Example fix

// before
let seg = NewSegment { start: f64::NAN, end: 30.0, .. };
// after
let start: f64 = "10".parse()?;
let seg = NewSegment { start, end: 30.0, .. };
Defensive patterns

Strategy: validation

Validate before calling

fn valid_times(seg: &NewSegment) -> bool {
    seg.start.is_finite() && seg.end.is_finite() && seg.start >= 0.0 && seg.end >= 0.0
}

Type guard

fn finite_nonnegative(x: f64) -> bool {
    x.is_finite() && x >= 0.0
}

Prevention

When it happens

Trigger: Calling `validate_segments`/`build_payload` with a segment where `start` or `end` is NaN, infinite, negative, or otherwise non-finite — typically from uninitialized UI fields, division results, or JSON parsed from bad data.

Common situations: Timestamp fields left empty becoming NaN in the UI; a buggy parser emitting -1 as a sentinel; deserializing segments from corrupted/edited JSON; float overflow computing timestamps.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

    }
    for (i, s) in segments.iter().enumerate() {
        let n = i + 1;
        if !CATEGORIES.contains(&s.category.as_str()) {
            return Err(anyhow!(
                "trecho {}: categoria desconhecida ({})",
                n,
                s.category
            ));
        }
        if !ACTION_TYPES.contains(&s.action_type.as_str()) {
            return Err(anyhow!(
                "trecho {}: tipo de ação desconhecido ({})",
                n,
                s.action_type
            ));
        }
        if !s.start.is_finite() || !s.end.is_finite() || s.start < 0.0 || s.end < 0.0 {
            return Err(anyhow!("trecho {}: tempo inválido", n));
        }
        let pontual = s.action_type == "poi" || s.action_type == "full";
        if !pontual && s.end <= s.start {
            return Err(anyhow!("trecho {}: o fim tem de vir depois do começo", n));
        }
        if s.action_type == "chapter" && s.description.trim().is_empty() {
            return Err(anyhow!("trecho {}: capítulo precisa de um título", n));
        }
        if duration > 0.0 && s.end > duration + 1.0 {
            return Err(anyhow!("trecho {}: passa do fim do vídeo", n));
        }
    }
    // Sobreposição só importa entre trechos que pulam pedaço.
    let mut cortes: Vec<&NewSegment> = segments
        .iter()
        .filter(|s| s.action_type == "skip" || s.action_type == "mute")
        .collect();
    cortes.sort_by(|a, b| a.start.total_cmp(&b.start));

View on GitHub (pinned to 8600b91f42)