{"record":{"id":"b5b3437786c2e7ea","repo":"SubtitleEdit/subtitleedit","slug":"yt-dlp-is-not-installed","errorCode":null,"errorMessage":"yt-dlp is not installed","messagePattern":"yt-dlp is not installed","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Download/YtDlpDownloadService.cs","lineNumber":219,"sourceCode":"            {\n                File.Delete(filePath);\n            }\n        }\n        catch\n        {\n            // Best-effort cleanup; a leftover bad file is re-checked on next download.\n        }\n    }\n\n    private static readonly Regex PercentageRegex = new(@\"(?<pct>\\d+(?:\\.\\d+)?)\\s*%\", RegexOptions.Compiled);\n\n    public async Task DownloadVideo(string url, string outputPath, bool downloadAllSubtitles, IProgress<float>? progress, CancellationToken cancellationToken, IProgress<YtDlpDownloadStage>? stageProgress = null)\n    {\n        cancellationToken.ThrowIfCancellationRequested();\n\n        if (!File.Exists(GetFullFileName()))\n        {\n            throw new InvalidOperationException(\"yt-dlp is not installed\");\n        }\n\n        var args = new List<string>\n        {\n            \"--newline\",       // emit one progress line per update, never carriage-return rewriting\n            \"--no-mtime\",      // don't carry remote mtime to the local file\n            \"--no-playlist\",   // single video only — playlist URLs would download many files\n            \"-o\", outputPath,\n        };\n\n        if (downloadAllSubtitles)\n        {\n            // Ride along with the video download: yt-dlp writes every available\n            // human-uploaded subtitle track as a sibling file using the same\n            // <stem>.<lang>.<ext> naming so the caller can find them by globbing.\n            args.Add(\"--write-subs\");\n            args.Add(\"--sub-langs\");\n            args.Add(\"all\");","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Download/YtDlpDownloadService.cs#L201-L237","documentation":"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.","triggerScenarios":"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).","commonSituations":"First-time use where the auto-download step was skipped/failed, or a portable install moved between machines without carrying the DataFolder.","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."],"exampleFix":"// before\nawait _ytDlp.DownloadVideo(url, outPath, false, progress, ct);\n\n// after\nif (!File.Exists(YtDlpDownloadService.GetFullFileName()))\n{\n    await _ytDlp.DownloadYtDlp(progress, ct); // install first\n}\nawait _ytDlp.DownloadVideo(url, outPath, false, progress, ct);","handlingStrategy":"validation","validationCode":"if (!File.Exists(YtDlpDownloadService.GetFullFileName()))\n    await svc.DownloadYtDlp(progress, ct);","typeGuard":"static bool IsYtDlpInstalled() => File.Exists(YtDlpDownloadService.GetFullFileName());","tryCatchPattern":"try { await svc.DownloadVideo(url, outPath, false, progress, ct); }\ncatch (InvalidOperationException ex) when (ex.Message == \"yt-dlp is not installed\")\n{ await svc.DownloadYtDlp(progress, ct); await svc.DownloadVideo(url, outPath, false, progress, ct); }","preventionTips":["Always run DownloadYtDlp (the installer) before any DownloadVideo call.","Check IsYtDlpInstalled() in the UI and disable video-download actions until the binary is present."],"tags":["yt-dlp","precondition","download","filesystem"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}