SubtitleEdit/subtitleedit · error · InvalidOperationException

yt-dlp exited with code {process.ExitCode}.

Error message

yt-dlp exited with code {process.ExitCode}.

What it means

Thrown by DownloadVideo after the yt-dlp process exits with a non-zero ExitCode. The captured stderr is appended to the message so the underlying yt-dlp error (bad URL, geo-block, rate limit, missing ffmpeg, private video) is visible. Cancellation is handled separately (TryKillProcess + rethrow) so this throw is only for genuine failure exits.

Source

Thrown at src/ui/Logic/Download/YtDlpDownloadService.cs:315

        }

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        try
        {
            await process.WaitForExitAsync(cancellationToken);
        }
        catch (OperationCanceledException)
        {
            TryKillProcess(process);
            throw;
        }

        if (process.ExitCode != 0)
        {
            var details = stderrBuffer.ToString().Trim();
            throw new InvalidOperationException(
                $"yt-dlp exited with code {process.ExitCode}." +
                (string.IsNullOrEmpty(details) ? string.Empty : Environment.NewLine + details));
        }

        progress?.Report(1f);
    }

    public Task DownloadAllSubtitlesAsync(string url, string outputStem, CancellationToken cancellationToken)
    {
        return DownloadSubtitlesOnlyAsync(url, outputStem, autoGenerated: false, cancellationToken);
    }

    public Task DownloadAutoGeneratedSubtitlesAsync(string url, string outputStem, CancellationToken cancellationToken)
    {
        return DownloadSubtitlesOnlyAsync(url, outputStem, autoGenerated: true, cancellationToken);
    }

    private async Task DownloadSubtitlesOnlyAsync(string url, string outputStem, bool autoGenerated, CancellationToken cancellationToken)

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Read the stderr details in the exception message — it usually names the exact yt-dlp error.
  2. Update yt-dlp (re-run DownloadYtDlp) — site-extractor breakage is the single most common cause and is fixed upstream frequently.
  3. For private/age-restricted videos, supply a cookies.txt via yt-dlp args.
  4. Ensure ffmpeg is installed and on PATH for post-processing merges.
  5. Retry after a delay if the message indicates HTTP 429 rate-limiting.

Example fix

// before
catch (InvalidOperationException ex) { log(ex.Message); }

// after: surface the embedded stderr and retry on rate-limit
try { await _ytDlp.DownloadVideo(url, outPath, false, progress, ct); }
catch (InvalidOperationException ex)
{
    if (ex.Message.Contains("429")) { await Task.Delay(TimeSpan.FromMinutes(2), ct); throw; }
    showUser(ex.Message); // includes yt-dlp stderr
    throw;
}
Defensive patterns

Strategy: try-catch

Try / catch

try { await svc.DownloadVideo(url, outPath, false, progress, ct); }
catch (InvalidOperationException ex)
{
    if (ex.Message.Contains("429")) { await Task.Delay(TimeSpan.FromMinutes(2), ct); throw; }
    showUser(ex.Message); throw;
}

Prevention

When it happens

Trigger: yt-dlp returns non-zero: invalid/private/region-blocked URL, YouTube rate-limiting (HTTP 429), ffmpeg not found for merging, network failure mid-download, or an outdated yt-dlp that no longer parses the site.

Common situations: Trying to download a private/age-restricted video without cookies; yt-dlp version is old and the extractor broke after a site change; ffmpeg missing on PATH for merge of separate audio/video.

Related errors


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