{"record":{"id":"ba0944d4c83b31ba","repo":"tonhowtf/omniget","slug":"no-video-quality-available-mod","errorCode":null,"errorMessage":"No video quality available","messagePattern":"No video quality available","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/platforms/twitch/mod.rs","lineNumber":56,"sourceCode":"        Self::new()\n    }\n}\n\nimpl TwitchClipsDownloader {\n    async fn fallback_ytdlp(&self, url: &str) -> anyhow::Result<MediaInfo> {\n        let ytdlp_path = crate::core::ytdlp::ensure_ytdlp().await?;\n        let json = crate::core::ytdlp::get_video_info(&ytdlp_path, url, &[]).await?;\n        crate::platforms::generic_ytdlp::GenericYtdlpDownloader::parse_video_info(&json)\n    }\n\n    async fn native_get_media_info(&self, url: &str) -> anyhow::Result<MediaInfo> {\n        let slug =\n            Self::extract_clip_slug(url).ok_or_else(|| anyhow!(\"Could not extract clip slug\"))?;\n\n        let clip = self.fetch_clip_metadata(&slug).await?;\n\n        if clip.video_qualities.is_empty() {\n            return Err(anyhow!(\"No video quality available\"));\n        }\n\n        let broadcaster = clip\n            .broadcaster_login\n            .as_deref()\n            .ok_or_else(|| anyhow!(\"Dados do clip incompletos\"))?;\n\n        let token = self.fetch_access_token(&slug).await?;\n\n        let clip_title = clip.title.trim().to_string();\n\n        let available_qualities: Vec<VideoQuality> = clip\n            .video_qualities\n            .iter()\n            .map(|q| {\n                let height: u32 = q.quality.parse().unwrap_or(0);\n                let authenticated_url = Self::build_authenticated_url(&q.source_url, &token);\n                VideoQuality {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/twitch/mod.rs#L38-L74","documentation":"After fetching clip metadata from Twitch's GQL endpoint, native_get_media_info checks that the clip's video_qualities list is non-empty before building MediaInfo. This error means Twitch returned clip metadata but with no downloadable renditions, so there is nothing to download.","triggerScenarios":"get_media_info → native_get_media_info where fetch_clip_metadata(slug) succeeds but the clip's videoQualities array is empty — clips pending deletion, clips from banned/suspended channels, or Twitch API returning a degraded response.","commonSituations":"Very old clips whose renditions expired; clips from channels banned after posting; intermittent Twitch GQL responses missing videoQualities; rate-limited or unauthenticated GQL calls returning partial data.","solutions":["Retry fetch_clip_metadata — Twitch GQL responses are sometimes transiently incomplete.","Verify the clip plays at clips.twitch.tv/<slug>; if deleted/banned, it cannot be downloaded.","Fall back to the yt-dlp path, which can resolve clip sources differently.","Check for Twitch API rate limiting or missing authentication headers in fetch_clip_metadata."],"exampleFix":"// before\nif clip.video_qualities.is_empty() {\n    return Err(anyhow!(\"No video quality available\"));\n}\n// after\nif clip.video_qualities.is_empty() {\n    return Err(anyhow!(\n        \"No video quality available for clip '{}' — it may be deleted or the channel banned\",\n        slug\n    ));\n}","handlingStrategy":"retry","validationCode":"// After fetching metadata, check renditions before building MediaInfo\nif clip.video_qualities.is_empty() {\n    eprintln!(\"clip metadata has no renditions; retry or check clip online\");\n}","typeGuard":"fn has_renditions(clip: &ClipMetadata) -> bool {\n    !clip.video_qualities.is_empty()\n}","tryCatchPattern":"match get_media_info(url).await {\n    Err(e) if e.to_string().contains(\"No video quality\") => retry_with_backoff(3).await,\n    other => other,\n}","preventionTips":["Retry once on empty renditions before treating the clip as dead.","Check the clip still plays on Twitch before automating the download.","Watch for GQL rate limiting and add authentication/backoff to fetch_clip_metadata."],"tags":["twitch","clip","empty-list","api-response"],"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"}