{"record":{"id":"247ca2c4242400f1","repo":"tonhowtf/omniget","slug":"could-not-extract-clip-slug","errorCode":null,"errorMessage":"Could not extract clip slug","messagePattern":"Could not extract clip slug","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/twitch.rs","lineNumber":51,"sourceCode":"    client: reqwest::Client,\n}\n\nimpl Default for TwitchClipsDownloader {\n    fn default() -> Self {\n        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","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/twitch.rs#L33-L69","documentation":"Raised by TwitchClipsDownloader::native_get_media_info when extract_clip_slug(url) returns None, i.e. the URL could not be parsed as a Twitch clip link (neither clips.twitch.tv/<slug> nor twitch.tv/<channel>/clip/<slug>).","triggerScenarios":"Passing a URL that is a full Twitch VOD, channel page, or a malformed/non-Twitch URL to get_media_info for a Twitch clip; e.g. https://twitch.tv/channel (no /clip segment) or a URL with query-embedding edge cases.","commonSituations":"Users paste a VOD or channel URL expecting clip download; a frontend passes an already-unwrapped player URL or a localized redirect URL the parser doesn't recognize.","solutions":["Validate the URL matches clips.twitch.tv/<slug> or twitch.tv/<channel>/clip/<slug> before calling","Ensure the URL is percent-decoded and free of tracking query parameters","Use the yt-dlp fallback path for non-clip Twitch URLs"],"exampleFix":"// before\nlet slug = Self::extract_clip_slug(url).ok_or_else(|| anyhow!(\"Could not extract clip slug\"))?;\n// after\nlet Some(slug) = Self::extract_clip_slug(url) else {\n    return self.fallback_ytdlp(url).await;\n};","handlingStrategy":"validation","validationCode":"const CLIP_RE: &str = r\"^(https?://)?(www\\.)?(clips\\.twitch\\.tv/[\\w-]+|twitch\\.tv/[\\w-]+/clip/[\\w-]+)\";\nlet ok = regex::Regex::new(CLIP_RE).unwrap().is_match(url);","typeGuard":"fn is_twitch_clip_url(url: &str) -> bool {\n    url::Url::parse(url).ok()\n        .and_then(|u| u.host_str().map(|h| h.to_lowercase()))\n        .map(|h| h.ends_with(\"twitch.tv\"))\n        .unwrap_or(false)\n        && (url.contains(\"clips.twitch.tv\") || url.contains(\"/clip/\"))\n}","tryCatchPattern":"match downloader.get_media_info(url).await {\n    Err(e) if e.to_string().contains(\"Could not extract clip slug\") => {\n        Err(anyhow::anyhow!(\"'{url}' is not a Twitch clip URL (expected clips.twitch.tv/<slug> or twitch.tv/<channel>/clip/<slug>)\"))\n    }\n    other => other,\n}","preventionTips":["Validate the URL is a clip link (host clips.twitch.tv or path segment /clip/) before calling","Strip query strings/UTM parameters before parsing","Distinguish VODs (/videos/) from clips and route them to the right downloader"],"tags":["rust","twitch","url-parsing","validation"],"backgroundTag":"invalid-url-format","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"}