{"record":{"id":"c9d7fcb76d4e798b","repo":"tonhowtf/omniget","slug":"resposta-sem-coment-rios-o-vod-tem-replay-de-chat","errorCode":null,"errorMessage":"resposta sem comentários (o VOD tem replay de chat?)","messagePattern":"resposta sem comentários \\(o VOD tem replay de chat\\?\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/twitch/chat.rs","lineNumber":133,"sourceCode":"    /// Amostra para a UI mostrar sem carregar tudo.\n    pub sample: Vec<Message>,\n}\n\n// ───────────────────────── parsing ─────────────────────────\n\n#[derive(Debug, Clone, Default)]\npub struct Page {\n    pub messages: Vec<Message>,\n    pub cursor: Option<String>,\n    pub has_next: bool,\n}\n\n/// Lê um elemento da resposta em lote da persisted query.\npub fn parse_page(raw: &Value) -> anyhow::Result<Page> {\n    let comments = raw\n        .pointer(\"/data/video/comments\")\n        .filter(|v| !v.is_null())\n        .ok_or_else(|| anyhow!(\"resposta sem comentários (o VOD tem replay de chat?)\"))?;\n    let edges = comments\n        .get(\"edges\")\n        .and_then(|v| v.as_array())\n        .cloned()\n        .unwrap_or_default();\n    let mut messages = Vec::with_capacity(edges.len());\n    let mut cursor = None;\n    for edge in &edges {\n        if let Some(c) = edge.get(\"cursor\").and_then(|v| v.as_str()) {\n            cursor = Some(c.to_string());\n        }\n        let Some(node) = edge.get(\"node\") else {\n            continue;\n        };\n        let Some(msg) = parse_message(node) else {\n            continue;\n        };\n        messages.push(msg);","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/twitch/chat.rs#L115-L151","documentation":"parse_page reads the batched persisted-query response for VOD chat comments. It throws when the JSON has no /data/video/comments path (or it is null), which the library interprets as the VOD having no chat replay. This is a defensive guard so callers get a clear message instead of a cryptic null-pointer failure.","triggerScenarios":"Calling fetch_all / msgs (or anything that calls parse_page) against a Twitch VOD whose chat replay is unavailable: the persisted query succeeds but data.video.comments is missing or null.","commonSituations":"Downloading chat for old VODs where replay was disabled or deleted by the broadcaster; VODs from before chat replay existed; streams where the channel enabled 'add chat replay' off; passing a VOD id with an expired/unavailable video (sometimes returns null comments instead of an error).","solutions":["Verify the VOD actually has chat replay by checking the video's comment section in a browser","Enable/keep 'Add chat replay' on the channel for future broadcasts — nothing can be recovered for past VODs","Use a different VOD id; confirm the id is correct and the video is not sub-only or expired","Handle this error as 'no chat available' in the caller instead of retrying"],"exampleFix":"// before\nlet page = fetch_all(&vod_id).await?;\n// after\nmatch fetch_all(&vod_id).await {\n    Ok(page) => println!(\"{} comments\", page.messages.len()),\n    Err(e) if e.to_string().contains(\"replay de chat\") => eprintln!(\"VOD has no chat replay\"),\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"// No pre-call check possible: chat replay availability is server-side.\n// Optionally verify the VOD page shows comments before invoking.","typeGuard":"fn has_chat_replay(raw: &serde_json::Value) -> bool {\n    raw.pointer(\"/data/video/comments\").map_or(false, |v| !v.is_null())\n}","tryCatchPattern":"match fetch_all(&vod_id).await {\n    Ok(page) => process(page),\n    Err(e) if e.to_string().contains(\"replay de chat\") => {\n        eprintln!(\"This VOD has no chat replay\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Check the VOD's chat tab in a browser before batch downloading","For your own channel, keep 'Add chat replay' enabled","Treat this error as terminal — retries will not create missing replay data","Validate the VOD id is a numeric Twitch video id"],"tags":["twitch","gql","chat-replay","vod"],"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"}