{"record":{"id":"c47e5748aaf6977d","repo":"tonhowtf/omniget","slug":"http-emotes","errorCode":null,"errorMessage":"HTTP {}","messagePattern":"HTTP \\{\\}","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/twitch/emotes.rs","lineNumber":830,"sourceCode":"    for attempt in 0..3 {\n        if attempt > 0 {\n            tokio::time::sleep(wait).await;\n            wait *= 2;\n        }\n        let resp = match http.get(url).send().await {\n            Ok(r) => r,\n            Err(e) => {\n                last = e.to_string();\n                continue;\n            }\n        };\n        let status = resp.status();\n        if status.as_u16() == 429 || status.is_server_error() {\n            last = format!(\"HTTP {}\", status);\n            continue;\n        }\n        if !status.is_success() {\n            anyhow::bail!(\"HTTP {}\", status);\n        }\n        let bytes = resp.bytes().await?;\n        if bytes.is_empty() {\n            anyhow::bail!(\"arquivo vazio\");\n        }\n        std::fs::write(path, &bytes)?;\n        return Ok(());\n    }\n    Err(anyhow!(\"{}\", last))\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn le_emotes_e_badges_da_twitch() {\n        let user = json!({","sourceCodeStart":812,"sourceCodeEnd":848,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/twitch/emotes.rs#L812-L848","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match emotes::run(&opts, &progress).await {\n    Err(e) if e.to_string().starts_with(\"HTTP 4\") => {\n        eprintln!(\"emote permanentemente indisponível ({}); continuando sem ele\", e);\n    }\n    other => other?,\n}","preventionTips":["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."],"tags":["twitch","emotes","download","http-404"],"backgroundTag":"http-non-2xx-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"}