{"record":{"id":"4f13772fb33c42b5","repo":"tonhowtf/omniget","slug":"esse-clipe-n-o-tem-vod-de-origem-ent-o-n-o-h-chat","errorCode":null,"errorMessage":"esse clipe não tem VOD de origem, então não há chat","messagePattern":"esse clipe não tem VOD de origem, então não há chat","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/twitch/gql.rs","lineNumber":255,"sourceCode":"            created_at: str_at(v, \"createdAt\"),\n            clip_offset: None,\n            clip_duration: None,\n        })\n    }\n\n    /// Clipe → VOD de origem, com a janela do clipe dentro dele.\n    pub async fn clip_video(&self, slug: &str) -> anyhow::Result<VideoInfo> {\n        let q = format!(\n            r#\"{{ clip(slug: \"{}\") {{ durationSeconds videoOffsetSeconds video {{ id }} }} }}\"#,\n            escape(slug)\n        );\n        let data = self.query(&q).await?;\n        let c = data.get(\"clip\").filter(|v| !v.is_null());\n        let c = c.ok_or_else(|| anyhow!(\"clipe não encontrado: {}\", slug))?;\n        let vid = c\n            .pointer(\"/video/id\")\n            .and_then(|x| x.as_str())\n            .ok_or_else(|| anyhow!(\"esse clipe não tem VOD de origem, então não há chat\"))?;\n        let mut info = self.video(vid).await?;\n        info.clip_offset = c.get(\"videoOffsetSeconds\").and_then(num);\n        info.clip_duration = c.get(\"durationSeconds\").and_then(num);\n        Ok(info)\n    }\n\n    /// Resolve o que o usuário colou até chegar num VOD.\n    pub async fn resolve_chat_target(&self, input: &str) -> anyhow::Result<VideoInfo> {\n        let target = parse_video(input)\n            .ok_or_else(|| anyhow!(\"cole o link de um VOD ou de um clipe da Twitch: {}\", input))?;\n        match target {\n            ChatTarget::Video(id) => self.video(&id).await,\n            ChatTarget::Clip(slug) => self.clip_video(&slug).await,\n        }\n    }\n}\n\nfn num(v: &Value) -> Option<f64> {","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/twitch/gql.rs#L237-L273","documentation":"clip_video() throws this when the clip exists but its video.id pointer is absent, i.e. the clip has no source VOD. Chat replay is stored on the VOD, so without a source video there is no chat to download for a clip. The library refuses rather than returning a video-less result.","triggerScenarios":"Calling gql.clip_video(slug) (or resolve_chat_target with a clip) for a clip whose source broadcast was deleted or expired after the clip was created, or clips made in contexts without an attached VOD.","commonSituations":"Old clips whose source stream was never saved or later deleted/expired; clips on channels that never keep VODs; asking for chat download on such a clip instead of the original stream's VOD.","solutions":["Accept that clip chat is unavailable and download the chat of an available VOD instead","Locate another clip of the same stream whose source VOD still exists","If the channel reuploaded/saved the stream, resolve the VOD id and use video()/fetch_all directly","Handle this error distinctly from 'clip not found' in caller UX"],"exampleFix":"// before\nlet target = resolve_chat_target(&arg).await?; // may be a sourceless clip\n// after\nlet target = match resolve_chat_target(&arg).await {\n    Ok(t) => t,\n    Err(e) if e.to_string().contains(\"não tem VOD de origem\") => {\n        eprintln!(\"clip has no source VOD; no chat replay exists\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n};","handlingStrategy":"try-catch","validationCode":"// Not checkable pre-call via this API; the clip's source-VOD link is only in the response.","typeGuard":null,"tryCatchPattern":"match gql.clip_video(slug).await {\n    Err(e) if e.to_string().contains(\"não tem VOD de origem\") => {\n        eprintln!(\"Clip exists but its source stream has no saved VOD — no chat replay\");\n        Ok(())\n    }\n    other => other,\n}","preventionTips":["Prefer resolving chat from the original VOD when you know its id","Don't assume every clip has a downloadable chat replay","Handle this distinctly from clip-not-found in UX messaging","Check the clip's page — it will show 'source video unavailable' when this applies"],"tags":["twitch","gql","clip","vod","chat-replay"],"backgroundTag":"entity-not-found","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"}