{"record":{"id":"3a58e9864a46c9ba","repo":"tonhowtf/omniget","slug":"no-quality-available","errorCode":null,"errorMessage":"No quality available","messagePattern":"No quality available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/generic_ytdlp.rs","lineNumber":268,"sourceCode":"            .map_err(|e| anyhow!(\"yt-dlp unavailable: {}\", e))?;\n\n        let extra = platform_extra_flags(url);\n        let json = ytdlp::get_video_info(&ytdlp_path, url, &extra).await?;\n        Self::parse_video_info(&json)\n    }\n\n    async fn download(\n        &self,\n        info: &MediaInfo,\n        opts: &DownloadOptions,\n        progress: mpsc::Sender<ProgressUpdate>,\n    ) -> anyhow::Result<DownloadResult> {\n        let _ = progress.send(ProgressUpdate::percent(0.0)).await;\n\n        let first = info\n            .available_qualities\n            .first()\n            .ok_or_else(|| anyhow!(\"No quality available\"))?;\n\n        let requested_height = opts\n            .quality\n            .as_deref()\n            .and_then(Self::extract_quality_height);\n\n        let selected = if let Some(h) = requested_height {\n            info.available_qualities\n                .iter()\n                .filter(|q| q.height > 0 && q.height <= h)\n                .max_by_key(|q| q.height)\n                .or_else(|| {\n                    opts.quality\n                        .as_deref()\n                        .and_then(|w| info.available_qualities.iter().find(|q| q.label == *w))\n                })\n                .unwrap_or(first)\n        } else if let Some(ref wanted) = opts.quality {","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/generic_ytdlp.rs#L250-L286","documentation":"In GenericYtdlpPlatform::download, the candidate stream is taken from the first element of info.available_qualities. If that vector is empty there is no format to select and the function aborts with 'No quality available'.","triggerScenarios":"download(opts) called with a MediaInfo built from parse_video_info where available_qualities ended up empty — e.g. yt-dlp JSON had no formats matching the filter, or the caller hand-built/passed an empty MediaInfo.","commonSituations":"Pages with only storyboard/m3u8 formats the parser skips; DRM or members-only content where yt-dlp returns no downloadable formats; outdated yt-dlp extractor returning empty formats; passing get_media_info output from a different platform into download.","solutions":["Run `yt-dlp -F <url>` manually to see whether real formats exist; if none, the content is restricted.","Update yt-dlp (yt-dlp -U) to pick up extractor fixes for the site.","Check parse_video_info's format filtering logic against the raw JSON to see why formats were dropped.","Validate available_qualities is non-empty in the caller before invoking download."],"exampleFix":"// before\nlet first = info.available_qualities.first()\n    .ok_or_else(|| anyhow!(\"No quality available\"))?;\n// after (caller-side guard)\nif info.available_qualities.is_empty() {\n    eprintln!(\"no formats extracted; refreshing MediaInfo / updating yt-dlp first\");\n    info = platform.get_media_info(&url).await?;\n}\nlet first = info.available_qualities.first().context(\"No quality available\")?;","handlingStrategy":"validation","validationCode":"if info.available_qualities.is_empty() {\n    eprintln!(\"no formats extracted for {url}; run `yt-dlp -F {url}` to inspect\");\n    return Err(anyhow!(\"refusing download: MediaInfo has zero qualities\"));\n}","typeGuard":"fn pick_quality<'a>(info: &'a MediaInfo, height: Option<u32>) -> Option<&'a Quality> {\n    match height {\n        Some(h) => info.available_qualities.iter().find(|q| q.height == Some(h)),\n        None => info.available_qualities.first(),\n    }\n}","tryCatchPattern":"match platform.download(opts).await {\n    Err(e) if e.to_string().contains(\"No quality available\") => {\n        let info = platform.get_media_info(url).await?;\n        if info.available_qualities.is_empty() {\n            Err(anyhow!(\"source exposes no downloadable formats (DRM/members-only?)\"))\n        } else {\n            platform.download(opts).await\n        }\n    }\n    other => other,\n}","preventionTips":["Check available_qualities before every download call.","Keep yt-dlp current — empty format lists are often extractor bugs fixed upstream.","Inspect raw `yt-dlp -F` output when formats look suspiciously empty."],"tags":["empty-list","quality-selection","rust","yt-dlp"],"backgroundTag":"empty-result-set","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}