SubtitleEdit/subtitleedit · error · InvalidOperationException
yt-dlp is not installed
Error message
yt-dlp is not installed
What it means
Thrown by DownloadVideo when the yt-dlp binary file does not exist at GetFullFileName() before launching it. This is a precondition check: the caller must run DownloadYtDlp (which downloads and verifies the binary) before attempting a video download. The check uses File.Exists so a missing, moved, or never-downloaded binary all trigger it.
Source
Thrown at src/ui/Logic/Download/YtDlpDownloadService.cs:219
{
File.Delete(filePath);
}
}
catch
{
// Best-effort cleanup; a leftover bad file is re-checked on next download.
}
}
private static readonly Regex PercentageRegex = new(@"(?<pct>\d+(?:\.\d+)?)\s*%", RegexOptions.Compiled);
public async Task DownloadVideo(string url, string outputPath, bool downloadAllSubtitles, IProgress<float>? progress, CancellationToken cancellationToken, IProgress<YtDlpDownloadStage>? stageProgress = null)
{
cancellationToken.ThrowIfCancellationRequested();
if (!File.Exists(GetFullFileName()))
{
throw new InvalidOperationException("yt-dlp is not installed");
}
var args = new List<string>
{
"--newline", // emit one progress line per update, never carriage-return rewriting
"--no-mtime", // don't carry remote mtime to the local file
"--no-playlist", // single video only — playlist URLs would download many files
"-o", outputPath,
};
if (downloadAllSubtitles)
{
// Ride along with the video download: yt-dlp writes every available
// human-uploaded subtitle track as a sibling file using the same
// <stem>.<lang>.<ext> naming so the caller can find them by globbing.
args.Add("--write-subs");
args.Add("--sub-langs");
args.Add("all");View on GitHub (pinned to 17a9f07487)
Solutions
- Call DownloadYtDlp first (it downloads + checksum-verifies the binary) and only call DownloadVideo once that succeeds.
- Check File.Exists(YtDlpDownloadService.GetFullFileName()) in the UI and trigger the download dialog when missing.
- Ensure Se.DataFolder is created and writable so the downloaded binary actually lands there.
- If an antivirus removed the binary, allow-list Se.DataFolder and re-run DownloadYtDlp.
Example fix
// before
await _ytDlp.DownloadVideo(url, outPath, false, progress, ct);
// after
if (!File.Exists(YtDlpDownloadService.GetFullFileName()))
{
await _ytDlp.DownloadYtDlp(progress, ct); // install first
}
await _ytDlp.DownloadVideo(url, outPath, false, progress, ct); Defensive patterns
Strategy: validation
Validate before calling
if (!File.Exists(YtDlpDownloadService.GetFullFileName()))
await svc.DownloadYtDlp(progress, ct); Type guard
static bool IsYtDlpInstalled() => File.Exists(YtDlpDownloadService.GetFullFileName());
Try / catch
try { await svc.DownloadVideo(url, outPath, false, progress, ct); }
catch (InvalidOperationException ex) when (ex.Message == "yt-dlp is not installed")
{ await svc.DownloadYtDlp(progress, ct); await svc.DownloadVideo(url, outPath, false, progress, ct); } Prevention
- Always run DownloadYtDlp (the installer) before any DownloadVideo call.
- Check IsYtDlpInstalled() in the UI and disable video-download actions until the binary is present.
When it happens
Trigger: Calling DownloadVideo before DownloadYtDlp has been run on this machine, or after the yt-dlp binary was deleted from Se.DataFolder (e.g. user cleared the folder, an antivirus quarantined it).
Common situations: First-time use where the auto-download step was skipped/failed, or a portable install moved between machines without carrying the DataFolder.
Related errors
- Unsupported OS platform
- Downloaded yt-dlp ({assetName}) failed SHA-256 verification
- File not found
- llama-server executable not found - please download llama.cp
- Could not find a free output filename for: {baseName}
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/b5b3437786c2e7ea.
Report an issue: GitHub.