tonhowtf/omniget · error
Twitch recusou o replay de chat
Error message
Twitch recusou o replay de chat: {} What it means
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.
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
Example fix
// before
export(&ExportOptions { video_id: "deleted_vod_id".into(), .. }).await?;
// after
let id = "valid_vod_id";
if twitch_vod_exists(id) && twitch_chat_available(id) {
export(&ExportOptions { video_id: id.into(), .. }).await?;
} Defensive patterns
Strategy: retry
Validate before calling
// validate VOD/chat availability before export
if !twitch_chat_replay_available(&video_id).await {
return Err(anyhow!("replay de chat indisponível para {}", video_id));
} Try / catch
match export(opts).await {
Err(e) if e.to_string().contains("Twitch recusou o replay de chat") => {
if is_rate_limit(&e) { tokio::time::sleep(BACKOFF).await; retry() }
else { eprintln!("VOD inválido/expirado ou Twitch fora do ar: {}", e); }
}
Err(e) => return Err(e),
Ok(r) => use(r),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Twitch GQL respondeu HTTP
- YouTube não retornou URL
- HTTP
- esse VOD não devolveu nenhuma mensagem de chat
- formato desconhecido
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/8fefb37b4c1019a6.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/twitch/chat.rs:399
report(p, ID, "started", 0, total, None);
loop {
let vars = match (use_cursor, cursor.as_ref()) {
(true, Some(c)) => json!({ "videoID": video_id, "cursor": c }),
_ => json!({ "videoID": video_id, "contentOffsetSeconds": offset }),
};
let raw = gql.persisted(OP, COMMENTS_HASH, vars).await?;
if let Some(msg) = first_error(&raw) {
let integrity = msg.to_lowercase().contains("integrity");
if integrity && use_cursor {
// A Twitch fechou o cursor para cliente anônimo: segue por
// offset, deduplicando pelas mensagens que já vieram.
use_cursor = false;
offset_fallback = true;
cursor = None;
continue;
}
bail!("Twitch recusou o replay de chat: {}", msg);
}
let page = parse_page(&raw)?;
pages += 1;
if page.messages.is_empty() {
break;
}
let last_offset = page
.messages
.iter()
.map(|m| m.offset)
.fold(offset, f64::max);
let mut fresh = 0usize;
for m in page.messages {
if m.offset < start || m.offset > end {
continue;
}
if seen.insert(m.id.clone()) {View on GitHub (pinned to 8600b91f42)