tonhowtf/omniget · error

o yt-dlp devolveu um JSON que não deu para ler

Error message

o yt-dlp devolveu um JSON que não deu para ler: {e}

What it means

Thrown by parse_listing in vimeo.rs when the JSON emitted by `yt-dlp --flat-playlist -J` cannot be deserialized with serde_json. It wraps the serde error, which includes position info. The library treats any yt-dlp stdout that is not valid JSON as fatal for listing operations.

Solutions

  1. Run the exact yt-dlp command manually (`yt-dlp --flat-playlist -J <url>`) and inspect what it prints to stdout.
  2. Update yt-dlp (`yt-dlp -U` or package manager) — Vimeo extraction breaks frequently and older versions emit errors instead of JSON.
  3. Ensure yt-dlp warnings go to stderr (add `--no-warnings` / correct `--progress` flags) so stdout is pure JSON.
  4. Check the serde error's `at line X column Y` offset to see what malformed content was returned.

Example fix

// before: trusting stdout blindly
let listing = parse_listing(&stdout)?;
// after: guard at the caller
if !stdout.trim_start().starts_with('{') {
    anyhow::bail!("yt-dlp não devolveu JSON (saída: {})", &stdout[..stdout.len().min(200)]);
}
let listing = parse_listing(&stdout)?;
Defensive patterns

Strategy: validation

Validate before calling

fn looks_like_json(s: &str) -> bool {
    let t = s.trim_start();
    t.starts_with('{') || t.starts_with('[')
}
// call before parse_listing:
if !looks_like_json(&stdout) { /* treat as yt-dlp failure, log stdout head */ }

Type guard

fn is_json_object(s: &str) -> bool {
    serde_json::from_str::<serde_json::Value>(s.trim()).map(|v| v.is_object()).unwrap_or(false)
}

Try / catch

match parse_listing(&stdout) {
    Err(e) if e.to_string().contains("não deu para ler") => {
        eprintln!("yt-dlp não devolveu JSON; atualize o yt-dlp e rode o comando manualmente");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling parse_listing (via the Vimeo listing/one/request paths) with stdout that is empty, HTML (e.g., a login or error page), a Python traceback, or JSON truncated by yt-dlp crashing mid-write.

Common situations: yt-dlp prints warnings/progress to stdout due to misconfigured flags; an old yt-dlp version outputs a different shape or crashes; a captive portal/proxy injects HTML; stdout gets polluted by shell profile output when spawned through a shell.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/vimeo.rs:652

        let is_playlist = item.get("_type").and_then(|t| t.as_str()) == Some("playlist")
            || item.get("entries").is_some();
        if is_playlist {
            collect_entries(item, out);
            continue;
        }
        if let Some(e) = entry_from_json(item) {
            if !out.iter().any(|x| x.id == e.id && !e.id.is_empty()) {
                out.push(e);
            }
        }
    }
}

/// Lê o JSON do `--flat-playlist -J`. Aceita playlist (showcase, álbum,
/// canal), playlist aninhada e o caso degenerado de um vídeo só.
pub fn parse_listing(json: &str) -> Result<ParsedListing> {
    let v: serde_json::Value = serde_json::from_str(json.trim())
        .map_err(|e| anyhow!("o yt-dlp devolveu um JSON que não deu para ler: {e}"))?;
    let id = v
        .get("id")
        .and_then(|x| x.as_str())
        .unwrap_or_default()
        .to_string();
    let title = v
        .get("title")
        .and_then(|x| x.as_str())
        .filter(|s| !s.trim().is_empty())
        .unwrap_or(&id)
        .to_string();
    let mut entries = Vec::new();
    collect_entries(&v, &mut entries);
    if entries.is_empty() && v.get("entries").is_none() {
        // Um vídeo só: o próprio objeto é a entrada.
        if let Some(e) = entry_from_json(&v) {
            entries.push(e);
        }

View on GitHub (pinned to 8600b91f42)