{"record":{"id":"8fefb37b4c1019a6","repo":"tonhowtf/omniget","slug":"twitch-recusou-o-replay-de-chat","errorCode":null,"errorMessage":"Twitch recusou o replay de chat: {}","messagePattern":"Twitch recusou o replay de chat: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/twitch/chat.rs","lineNumber":399,"sourceCode":"\n    report(p, ID, \"started\", 0, total, None);\n    loop {\n        let vars = match (use_cursor, cursor.as_ref()) {\n            (true, Some(c)) => json!({ \"videoID\": video_id, \"cursor\": c }),\n            _ => json!({ \"videoID\": video_id, \"contentOffsetSeconds\": offset }),\n        };\n        let raw = gql.persisted(OP, COMMENTS_HASH, vars).await?;\n        if let Some(msg) = first_error(&raw) {\n            let integrity = msg.to_lowercase().contains(\"integrity\");\n            if integrity && use_cursor {\n                // A Twitch fechou o cursor para cliente anônimo: segue por\n                // offset, deduplicando pelas mensagens que já vieram.\n                use_cursor = false;\n                offset_fallback = true;\n                cursor = None;\n                continue;\n            }\n            bail!(\"Twitch recusou o replay de chat: {}\", msg);\n        }\n        let page = parse_page(&raw)?;\n        pages += 1;\n        if page.messages.is_empty() {\n            break;\n        }\n\n        let last_offset = page\n            .messages\n            .iter()\n            .map(|m| m.offset)\n            .fold(offset, f64::max);\n        let mut fresh = 0usize;\n        for m in page.messages {\n            if m.offset < start || m.offset > end {\n                continue;\n            }\n            if seen.insert(m.id.clone()) {","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/twitch/chat.rs#L381-L417","documentation":"The Twitch chat replay fetcher pages through chat history via the Twitch API. When the API responds with an error, the tool retries with a cursor-less offset fallback; if the failure persists (or is not the fallback-eligible case), it bails with Twitch's own error message interpolated into this message.","triggerScenarios":"Calling export/fetch_all when the Twitch chat-replay endpoint returns an error — invalid video/VOD ID, VOD too old or deleted (sub-only chat expiration), rate limiting, or Twitch API outage — and it is not recoverable by the offset fallback.","commonSituations":"Using a video ID for a live stream with no replay yet; a VOD older than the chat retention window; expired/deleted VOD; transient 5xx or 429 responses; network blocking Twitch API access.","solutions":["Check that the video/VOD ID is valid and the VOD still exists with chat replay available","Retry later if the message indicates rate limiting or a Twitch-side error (429/5xx)","Confirm the VOD is within Twitch's chat retention window (chat expires ~14 days for most, shorter for subs-only mode)","Verify network access / API tokens used by the underlying client","Inspect the interpolated `msg` in the error to identify Twitch's exact complaint"],"exampleFix":"// before\nexport(&ExportOptions { video_id: \"deleted_vod_id\".into(), .. }).await?;\n// after\nlet id = \"valid_vod_id\";\nif twitch_vod_exists(id) && twitch_chat_available(id) {\n    export(&ExportOptions { video_id: id.into(), .. }).await?;\n}","handlingStrategy":"retry","validationCode":"// validate VOD/chat availability before export\nif !twitch_chat_replay_available(&video_id).await {\n    return Err(anyhow!(\"replay de chat indisponível para {}\", video_id));\n}","typeGuard":null,"tryCatchPattern":"match export(opts).await {\n    Err(e) if e.to_string().contains(\"Twitch recusou o replay de chat\") => {\n        if is_rate_limit(&e) { tokio::time::sleep(BACKOFF).await; retry() }\n        else { eprintln!(\"VOD inválido/expirado ou Twitch fora do ar: {}\", e); }\n    }\n    Err(e) => return Err(e),\n    Ok(r) => use(r),\n}","preventionTips":["Validate the VOD ID exists and has chat replay before exporting","Respect Twitch rate limits with backoff/retry","Remember chat expires (~14 days); export replays promptly","Handle transient 5xx with a bounded retry loop"],"tags":["twitch","api","chat","network"],"backgroundTag":"api-error-response","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"}