tonhowtf/omniget · error

não foi possível iniciar o yt-dlp

Error message

não foi possível iniciar o yt-dlp: {e}

What it means

Thrown by run_json in vimeo.rs when spawning the yt-dlp child process fails (cmd.output() io error) at vimeo.rs:751. yt-dlp was resolved to a path but exec failed — distinct from a non-zero yt-dlp exit, which produces the vimeo:{code} or raw-stderr errors instead.

Solutions

  1. Check the wrapped io::Error kind: NotFound means the resolved path vanished — re-run ensure_ytdlp to reinstall.
  2. Verify the binary is executable (`ls -l $(which yt-dlp)`) and its shebang interpreter exists (`head -1 $(which yt-dlp)`).
  3. If spawn fails under load, raise process/fd limits or serialize yt-dlp invocations.
  4. Re-download yt-dlp if the file is corrupt (`yt-dlp -U` or delete the managed copy and retry).

Example fix

// before
let out = cmd.output().await.map_err(|e| anyhow!("não foi possível iniciar o yt-dlp: {e}"))?;
// after: self-heal once
let out = match cmd.output().await {
    Ok(o) => o,
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
        crate::core::ytdlp::ensure_ytdlp().await?;
        cmd.output().await? 
    }
    Err(e) => return Err(anyhow!("não foi possível iniciar o yt-dlp: {e}")),
};
Defensive patterns

Strategy: retry

Validate before calling

let bin = ytdlp_bin().await?;
if !bin.exists() {
    crate::core::ytdlp::ensure_ytdlp().await?; // re-acquire before spawning
}

Try / catch

match run_json(&bin, &args, &secrets).await {
    Err(e) if e.to_string().contains("não foi possível iniciar o yt-dlp") => {
        let bin2 = ytdlp_bin().await?; // re-resolve and retry once
        run_json(&bin2, &args, &secrets).await
    }
    other => other,
}

Prevention

When it happens

Trigger: run_json building `ytdlp_command(bin)` and calling .output(): exec fails because the resolved path no longer exists, the file lost its exec bit, the interpreter in its shebang is missing, or fork/resource limits block spawn.

Common situations: Managed yt-dlp download removed by a cleanup job between ensure and spawn; script-mode install whose `python3` is absent; ENOEXEC on a truncated/corrupt download; low fd/process limits under concurrent enumeration.

Related errors


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

Appendix: source

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

}

// ───────────────────────── execução ─────────────────────────

async fn ytdlp_bin() -> Result<PathBuf> {
    crate::core::ytdlp::ensure_ytdlp()
        .await
        .map_err(|e| anyhow!("o yt-dlp não está disponível: {e}"))
}

/// Roda o yt-dlp e devolve o stdout inteiro. Usado só pela enumeração.
async fn run_json(bin: &Path, args: &[String], secrets: &[&str]) -> Result<String> {
    let _slot = crate::core::ytdlp::acquire_ytdlp_slot("vimeo-list").await;
    let mut cmd = crate::core::ytdlp::ytdlp_command(bin);
    cmd.args(args).stdin(std::process::Stdio::null());
    let out = cmd
        .output()
        .await
        .map_err(|e| anyhow!("não foi possível iniciar o yt-dlp: {e}"))?;
    if !out.status.success() {
        let tail = scrub(&String::from_utf8_lossy(&out.stderr), secrets);
        let msg = tail
            .lines()
            .rev()
            .find(|l| !l.trim().is_empty())
            .unwrap_or("")
            .to_string();
        return Err(match error_code(&msg) {
            Some(code) => anyhow!("vimeo:{code}"),
            None => anyhow!("{}", msg),
        });
    }
    Ok(String::from_utf8_lossy(&out.stdout).to_string())
}

/// O que sobrou de um download. `tail` já passou pelo `scrub`.
struct DownloadOutcome {

View on GitHub (pinned to 8600b91f42)