SubtitleEdit/subtitleedit · error · FileNotFoundException

yt-dlp finished but no video file was produced. Temp directo

Error message

yt-dlp finished but no video file was produced.
Temp directory: {tempDir}
Contents: {files}

What it means

Thrown when yt-dlp exits without error but FindProducedVideo cannot locate any valid video file in the temp directory. FindProducedVideo enumerates files matching 'download.*', excluding subtitle sidecars (names with two dots like 'download.en.srt') and incomplete '.part' files. If nothing remains, the download is treated as failed despite yt-dlp reporting success.

Source

Thrown at src/ui/Features/Video/OpenFromUrl/DownloadVideoFromUrlViewModel.cs:169

        // Pass yt-dlp the literal "%(ext)s" placeholder so it picks the actual
        // container extension. If we use the user's chosen extension verbatim
        // (e.g. "download.mkv"), yt-dlp treats the whole thing as the template
        // stem and writes "download.mkv.webm" after the merge — leaving us
        // unable to find the produced file by predicted name.
        var templatePath = Path.Combine(tempDir, "download.%(ext)s");

        try
        {
            await _ytDlpDownloadService.DownloadVideo(_url, templatePath, _downloadSubtitles, progress, cancellationToken, stageProgress);

            // Everything from here on is silent too: moving the file out of the temp dir can
            // be a full copy across volumes, and the auto-caption fetch is another yt-dlp run.
            stageProgress.Report(YtDlpDownloadStage.PostProcessing);

            var actualVideoPath = FindProducedVideo(tempDir);
            if (actualVideoPath is null)
            {
                throw new FileNotFoundException(
                    "yt-dlp finished but no video file was produced." + Environment.NewLine +
                    $"Temp directory: {tempDir}" + Environment.NewLine +
                    "Contents: " + (Directory.Exists(tempDir)
                        ? string.Join(", ", Directory.EnumerateFiles(tempDir).Select(Path.GetFileName))
                        : "<missing>"));
            }

            if (File.Exists(OutputPath))
            {
                File.Delete(OutputPath);
            }
            File.Move(actualVideoPath, OutputPath);

            if (_downloadSubtitles)
            {
                if (_includeAutoGeneratedSubtitles)
                {
                    try

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Check the temp directory contents listed in the error message to see what yt-dlp actually wrote.
  2. Verify ffmpeg/ffprobe is installed and on PATH — yt-dlp needs it for merging separate audio/video streams.
  3. Update yt-dlp to the latest version (yt-dlp self-update or reinstall).
  4. Test the URL directly with yt-dlp from the command line using the same -o template to see what filename it produces.
  5. If the URL is audio-only, use an audio download flow instead of video.
  6. Check yt-dlp's --verbose output for merge failures or post-processing errors.

Example fix

// before
var actualVideoPath = FindProducedVideo(tempDir);
if (actualVideoPath is null)
{
    throw new FileNotFoundException(
        "yt-dlp finished but no video file was produced." + Environment.NewLine +
        $"Temp directory: {tempDir}" + Environment.NewLine +
        "Contents: " + (Directory.Exists(tempDir)
            ? string.Join(", ", Directory.EnumerateFiles(tempDir).Select(Path.GetFileName))
            : "<missing>"));
}

// after — broaden the search and include yt-dlp's own output in the message
var actualVideoPath = FindProducedVideo(tempDir);
if (actualVideoPath is null)
{
    // Fall back: accept any non-subtitle, non-part file in the temp dir
    var allFiles = Directory.Exists(tempDir)
        ? Directory.EnumerateFiles(tempDir).ToList()
        : new List<string>();
    actualVideoPath = allFiles.FirstOrDefault(f =>
    {
        var ext = Path.GetExtension(f).ToLowerInvariant();
        return !new[] { ".srt", ".vtt", ".ass", ".ssa", ".sub", ".part" }.Contains(ext);
    });
}
if (actualVideoPath is null)
{
    throw new FileNotFoundException(
        "yt-dlp finished but no video file was produced." + Environment.NewLine +
        $"Temp directory: {tempDir}" + Environment.NewLine +
        "Contents: " + (Directory.Exists(tempDir)
            ? string.Join(", ", Directory.EnumerateFiles(tempDir).Select(Path.GetFileName))
            : "<missing>"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate the URL with yt-dlp's --simulate flag
var psi = new ProcessStartInfo("yt-dlp", $"--simulate --no-warnings \"{_url}\"")
{ RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false };
using var proc = Process.Start(psi);
await proc.WaitForExitAsync();
if (proc.ExitCode != 0)
    throw new InvalidOperationException("yt-dlp cannot resolve URL: " + _url);

Try / catch

try { await _ytDlpDownloadService.DownloadVideo(...); }
catch (FileNotFoundException ex) when (ex.Message.Contains("no video file was produced"))
{ /* read temp dir contents from message, check for .part files (incomplete), suggest ffmpeg install or retry */ }

Prevention

When it happens

Trigger: yt-dlp writes the final file with a name that doesn't match 'download.*' (e.g. it used a different template stem); yt-dlp wrote only subtitle files and no video; the merge step failed silently leaving only .part files; the output was written to a different directory than tempDir; yt-dlp completed but the temp directory was concurrently cleaned.

Common situations: yt-dlp version upgrade changed default output naming behaviour; the URL is audio-only or subtitle-only with no video stream; yt-dlp's merge step (e.g. ffmpeg) is missing and it leaves fragmented .part files; the template path with %(ext)s was overridden by yt-dlp config; a concurrent cleanup process removed the temp dir.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/d5952adccb7aa5e7. Report an issue: GitHub.