tonhowtf/omniget · error
HTTP
Error message
HTTP {} What it means
fetch_one() downloads an individual emote image file. Statuses 429 and 5xx are retried (stored in `last`), but any other non-success status (e.g. 403, 404) immediately bails with "HTTP <status>". This means the emote image URL is definitively not fetchable and retrying won't help.
Solutions
- Treat that emote as unavailable: skip it and re-run to fetch the remaining emotes.
- Refresh the emote list so deleted emotes are no longer requested.
- If 403, check whether the client needs a browser-like User-Agent or authentication headers.
- Verify the image URL manually in a browser to confirm it is dead.
Defensive patterns
Strategy: try-catch
Try / catch
match emotes::run(&opts, &progress).await {
Err(e) if e.to_string().starts_with("HTTP 4") => {
eprintln!("emote permanentemente indisponível ({}); continuando sem ele", e);
}
other => other?,
} Prevention
- Refresh the emote list before downloading so deleted emotes are skipped.
- Send a browser-like User-Agent to avoid hotlink-protection 403s.
- Distinguish permanent statuses (403/404) from retriable ones (429/5xx) when wrapping calls.
- Log the failing URL (parsed from prior json_get output) to identify dead emotes.
When it happens
Trigger: Calling run() when an emote image URL returns 404 (emote deleted from the provider), 403 (hotlink protection/blocked), or other permanent non-success statuses; also reached after exhausting retries with a terminal status.
Common situations: Downloading emote packs where some emotes were deleted on 7TV/BTTV/FFZ since listing; CDN hotlink protection rejecting non-browser User-Agents; region-blocked CDN edges.
Related errors
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/c47e5748aaf6977d.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/twitch/emotes.rs:830
for attempt in 0..3 {
if attempt > 0 {
tokio::time::sleep(wait).await;
wait *= 2;
}
let resp = match http.get(url).send().await {
Ok(r) => r,
Err(e) => {
last = e.to_string();
continue;
}
};
let status = resp.status();
if status.as_u16() == 429 || status.is_server_error() {
last = format!("HTTP {}", status);
continue;
}
if !status.is_success() {
anyhow::bail!("HTTP {}", status);
}
let bytes = resp.bytes().await?;
if bytes.is_empty() {
anyhow::bail!("arquivo vazio");
}
std::fs::write(path, &bytes)?;
return Ok(());
}
Err(anyhow!("{}", last))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn le_emotes_e_badges_da_twitch() {
let user = json!({View on GitHub (pinned to 8600b91f42)