{"record":{"id":"86b3de6ee0da52b5","repo":"tonhowtf/omniget","slug":"dados-do-clip-incompletos","errorCode":null,"errorMessage":"Dados do clip incompletos","messagePattern":"Dados do clip incompletos","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/twitch.rs","lineNumber":62,"sourceCode":"        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 {\n                    label: format!(\"{}p\", q.quality),\n                    width: 0,\n                    height,\n                    url: authenticated_url,\n                    format: \"mp4\".to_string(),\n                }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/twitch.rs#L44-L80","documentation":"Raised by native_get_media_info when clip.broadcaster_login is None despite the clip record existing, i.e. the GraphQL response lacks /data/clip/broadcaster/login. The download layer requires the broadcaster login as the MediaInfo author field.","triggerScenarios":"The GQL clip response omits or nulls the broadcaster object — e.g. a banned/deactivated broadcaster, partial GQL error responses, or schema changes renaming the field.","commonSituations":"The broadcaster account was banned or renamed so login is null; a partial GraphQL response (errors array plus null data fields) is treated as success.","solutions":["Check the raw GQL response for a partial-errors payload before treating data as complete","Fall back to curator.login or the slug when broadcaster_login is missing","Route to the yt-dlp fallback which derives the uploader independently"],"exampleFix":"// before\nlet broadcaster = clip.broadcaster_login.as_deref().ok_or_else(|| anyhow!(\"Dados do clip incompletos\"))?;\n// after\nlet broadcaster = clip.broadcaster_login.as_deref()\n    .or(clip.curator_login.as_deref())\n    .unwrap_or(\"unknown\");","handlingStrategy":"fallback","validationCode":"// Inspect the GQL clip JSON yourself before relying on native extraction:\nlet broadcaster_missing = json.pointer(\"/data/clip/broadcaster/login\").is_none();","typeGuard":null,"tryCatchPattern":"match downloader.get_media_info(url).await {\n    Err(e) if e.to_string().contains(\"Dados do clip incompletos\") => fallback_ytdlp_info(url).await,\n    other => other,\n}","preventionTips":["Check the GQL response errors array — partial data with errors can lack broadcaster","Fall back to curator.login when broadcaster is null","Prefer yt-dlp for clips from banned/deactivated channels"],"tags":["rust","twitch","null-value","api"],"backgroundTag":"unexpected-response-shape","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"}