tonhowtf/omniget · error
Failed to run yt-dlp
Error message
Failed to run yt-dlp: {} What it means
This error is raised in get_video_info when the yt-dlp child process cannot be spawned via tokio::process::Command::spawn(). It wraps the underlying io::Error, so it fires before any network or parsing work happens. Typically the yt-dlp binary is missing, not executable, or the configured path is wrong.
Solutions
- Verify the yt-dlp binary path exists and is executable (chmod +x, or reinstall yt-dlp)
- Log the io::Error kind to distinguish NotFound vs PermissionDenied and fix accordingly
- If relying on PATH, ensure PATH inside the app process includes the yt-dlp location
- Retry after fixing; the code already loops attempts but spawn failure is not transient
Example fix
// before
let child = ytdlp_command(ytdlp).args(&args).spawn().map_err(|e| anyhow!("Failed to run yt-dlp: {}", e))?;
// after
let child = ytdlp_command(ytdlp).args(&args).spawn().map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
anyhow!("yt-dlp binary not found at '{}'; install yt-dlp or fix the configured path", ytdlp)
} else {
anyhow!("Failed to run yt-dlp: {}", e)
}
})?; Defensive patterns
Strategy: try-catch
Validate before calling
let meta = std::fs::metadata(ytdlp);
if meta.is_err() { return Err("yt-dlp binary not found at configured path".into()); }
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
if meta.unwrap().permissions().mode() & 0o111 == 0 {
return Err("yt-dlp binary is not executable".into());
}
} Type guard
fn yt_dlp_binary_ok(path: &str) -> bool {
std::fs::metadata(path).map(|m| m.is_file()).unwrap_or(false)
} Try / catch
match get_video_info(url).await {
Err(e) if e.to_string().contains("Failed to run yt-dlp") => {
// binary missing/not executable: prompt install or path fix
}
Err(e) => return Err(e),
Ok(info) => info,
} Prevention
- Ship and verify the yt-dlp binary at startup with a version check (yt-dlp --version)
- Never let users set a raw binary path without validating existence and exec permission
- In packaged apps, ensure the bundled binary keeps the executable bit (e.g. set in build scripts)
- Log the io::Error kind, not just the message, for faster diagnosis
When it happens
Trigger: Calling get_video_info with a `ytdlp` path that does not exist, is not executable, or resolves to a binary that fails to exec (e.g. permission denied, ENOENT); also OS-level process spawn limits being exhausted after all retry attempts.
Common situations: yt-dlp not installed or not on PATH; bundled binary shipped without the executable bit; users overriding the yt-dlp path with a typo'd setting; running inside a container/sandbox that forbids exec of that path.
Related errors
- Failed to start yt-dlp
- escolha a pasta de destino para organizar
- informe um appid, um link da loja ou marque a biblioteca…
- não achei appid para
- pasta de origem não encontrada
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/47ee055767b22236.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/ytdlp.rs:2319
);
log_hook::emit_log(dl_id, &line);
}
}
if let Some(proxy_url) = proxy {
args.push("--proxy".to_string());
args.push(proxy_url);
}
args.extend(extra_flags.iter().cloned());
args.push(url.to_string());
let _slot = acquire_ytdlp_slot("video info").await;
let child = ytdlp_command(ytdlp)
.args(&args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.kill_on_drop(true)
.spawn()
.map_err(|e| anyhow!("Failed to run yt-dlp: {}", e))?;
tracing::debug!(
"[perf] get_video_info: yt-dlp process spawned at {:?} (attempt {})",
_timer_start.elapsed(),
attempt + 1
);
let result = tokio::time::timeout(
std::time::Duration::from_secs(VIDEO_INFO_PROCESS_TIMEOUT_SECS),
child.wait_with_output(),
)
.await
.map_err(|_| {
tracing::debug!("[perf] get_video_info took {:?}", _timer_start.elapsed());
anyhow!(
"Timeout fetching video info ({}s)",
VIDEO_INFO_PROCESS_TIMEOUT_SECS
)
})?View on GitHub (pinned to 8600b91f42)