Tyrrrz/YoutubeDownloader · error · InvalidOperationException
No suitable download option found.
Error message
No suitable download option found.
What it means
Thrown by VideoDownloader.GetBestDownloadOptionAsync when preference.TryGetBestOption(options) returns null - none of the resolved stream options satisfy the user's VideoDownloadPreference (container + video-quality preference). The options come from VideoDownloadOption.ResolveAll(manifest, ...) over the stream manifest fetched from YouTube via YoutubeExplode.
Source
Thrown at YoutubeDownloader.Core/Downloading/VideoDownloader.cs:44
var manifest = await _youtube.Videos.Streams.GetManifestAsync(videoId, cancellationToken);
return VideoDownloadOption.ResolveAll(manifest, includeLanguageSpecificAudioStreams);
}
public async Task<VideoDownloadOption> GetBestDownloadOptionAsync(
VideoId videoId,
VideoDownloadPreference preference,
bool includeLanguageSpecificAudioStreams = true,
CancellationToken cancellationToken = default
)
{
var options = await GetDownloadOptionsAsync(
videoId,
includeLanguageSpecificAudioStreams,
cancellationToken
);
return preference.TryGetBestOption(options)
?? throw new InvalidOperationException("No suitable download option found.");
}
public async Task DownloadVideoAsync(
string filePath,
IVideo video,
VideoDownloadOption downloadOption,
bool includeSubtitles = true,
string? ffmpegPath = null,
IProgress<Percentage>? progress = null,
CancellationToken cancellationToken = default
)
{
// Include subtitles in the output container
var trackInfos = new List<ClosedCaptionTrackInfo>();
if (includeSubtitles && !downloadOption.Container.IsAudioOnly)
{
var manifest = await _youtube.Videos.ClosedCaptions.GetManifestAsync(
video.Id,View on GitHub (pinned to bbcff03951)
Solutions
- Broaden the VideoDownloadPreference (allow MP4 and WebM, multiple quality tiers) so TryGetBestOption has candidates.
- Call GetDownloadOptionsAsync first and choose from the returned list, or iterate progressively relaxed preferences until one yields an option.
- Re-fetch the manifest (availability is transient) and verify access - authenticate with cookies for age/login-gated videos before retrying.
Example fix
// before: throws when nothing matches the strict preference
var option = await downloader.GetBestDownloadOptionAsync(videoId, preference, ct);
// after: inspect available options and pick a safe fallback
var options = await downloader.GetDownloadOptionsAsync(videoId, includeLanguageSpecificAudioStreams: true, ct);
var option = preference.TryGetBestOption(options)
?? options.FirstOrDefault()
?? throw new InvalidOperationException("Video has no downloadable streams."); Defensive patterns
Strategy: validation
Validate before calling
var options = await downloader.GetDownloadOptionsAsync(
videoId, includeLanguageSpecificAudioStreams: true, ct);
if (options.Count is 0)
{
// tell the user the video has no downloadable streams (private/removed/live/restricted)
}
var chosen = preference.TryGetBestOption(options);
if (chosen is null)
{
// surface the actually-available containers/qualities and relax the preference
} Try / catch
VideoDownloadOption option;
try
{
option = await downloader.GetBestDownloadOptionAsync(videoId, preference, cancellationToken: ct);
}
catch (InvalidOperationException ex) when (ex.Message == "No suitable download option found.")
{
var fallback = await downloader.GetDownloadOptionsAsync(videoId, cancellationToken: ct);
option = fallback.FirstOrDefault() ?? throw;
} Prevention
- Surface the available containers/qualities to the user so their preference is informed.
- Default to permissive preferences and include language-specific audio streams.
- Resolve access restrictions (cookies/login) before offering the download.
When it happens
Trigger: The manifest contains no combination matching the preference: preference demands MP4 but only WebM/adaptive streams exist; the requested quality tier isn't published; the video is audio-only, a live stream, age-restricted, membership/premium-only, region-blocked, or removed; or includeLanguageSpecificAudioStreams=false filtered out the only audio track needed to pair with a video stream.
Common situations: A restrictive container/quality preference; YouTube rotating codecs so the preferred container disappears for a video; missing cookies for login/age-gated content; language-specific audio excluded leaving nothing muxable; access-restricted or transiently unavailable streams.
AI-assisted analysis of Tyrrrz/YoutubeDownloader@bbcff03951 (2026-08-13).
Data as JSON: /api/errors/4a8ca1365736fee0.
Report an issue: GitHub.