{"record":{"id":"30e9be52c8874a3e","repo":"zeroclaw-labs/zeroclaw","slug":"too-many-generated-image-redirects-max-max-image","errorCode":null,"errorMessage":"Too many generated image redirects (max {MAX_IMAGE_REDIRECTS})","messagePattern":"Too many generated image redirects \\(max (.+?)\\)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/image_gen.rs","lineNumber":271,"sourceCode":"    async fn download_generated_image(\n        image_url: &str,\n        nat64_prefixes: &[domain_guard::Nat64Prefix],\n    ) -> anyhow::Result<Vec<u8>> {\n        let mut current_url =\n            reqwest::Url::parse(image_url).context(\"Invalid generated image URL\")?;\n\n        for redirect_count in 0..=MAX_IMAGE_REDIRECTS {\n            let (target, client) =\n                prepare_generated_image_target(current_url.as_str(), nat64_prefixes).await?;\n            let response = client\n                .get(target.url.clone())\n                .send()\n                .await\n                .context(\"Failed to download generated image\")?;\n\n            if response.status().is_redirection() {\n                if redirect_count == MAX_IMAGE_REDIRECTS {\n                    anyhow::bail!(\"Too many generated image redirects (max {MAX_IMAGE_REDIRECTS})\");\n                }\n                let location = response\n                    .headers()\n                    .get(LOCATION)\n                    .ok_or_else(|| anyhow::Error::msg(\"Generated image redirect omitted Location\"))?\n                    .to_str()\n                    .context(\"Generated image redirect Location is not valid text\")?;\n                current_url = resolve_redirect_url(&target.url, location)?;\n                continue;\n            }\n\n            if !response.status().is_success() {\n                anyhow::bail!(\n                    \"Generated image download failed with HTTP {}\",\n                    response.status()\n                );\n            }\n","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/image_gen.rs#L253-L289","documentation":"Thrown by ZeroClaw's image generation tool when downloading the generated image from fal.ai follows more than 10 HTTP redirects. The downloader builds its reqwest client with redirect Policy::none() and walks Location headers manually, re-running the NAT64/domain guard on every hop; the loop at crates/zeroclaw-tools/src/image_gen.rs:260 is bounded by MAX_IMAGE_REDIRECTS = 10. Seeing this error means the 11th response in the chain was still a 3xx.","triggerScenarios":"The image URL returned by the fal.ai generation call never terminates in a 2xx within 10 hops: a circular redirect (host A redirects to B and back), a CDN/shortener chain longer than 10 links, or a misbehaving endpoint that always answers 301/302. Because resolve_redirect_url re-resolves every Location, alternating redirect targets also produce the loop.","commonSituations":"fal.ai changing its media CDN layout; a corporate proxy or captive portal injecting extra redirects in front of the agent; dual-stack/NAT64 environments where a host alternates between two redirect targets; a stale zeroclaw-tools build pointing at a deprecated fal.ai storage domain.","solutions":["Take the image URL from the surrounding error context and follow it manually with curl -I to see the Location chain and where it loops or stalls","Retry the whole generation call - a fresh image URL usually avoids the bad chain","Bypass or allowlist the fal.ai media hosts on any redirect-injecting proxy or captive portal in front of the agent","Only if the chain legitimately exceeds 10 hops, raise MAX_IMAGE_REDIRECTS (crates/zeroclaw-tools/src/image_gen.rs:16) and rebuild"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"fn is_redirect_overflow(err: &anyhow::Error) -> bool {\n    err.to_string()\n        .starts_with(\"Too many generated image redirects\")\n}","tryCatchPattern":"match image_gen.execute(args).await {\n    Ok(result) => result,\n    Err(e) if is_redirect_overflow(&e) => {\n        // deterministic loop: never retry the same URL;\n        // fall back to regenerating the image for a fresh URL\n        regenerate_or_report(e)\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep fal.ai media hosts outside any redirect-wrapping proxy or captive portal","Pin a current zeroclaw-tools build so the fal.ai URL contract matches the live API","Log the failing image URL once per incident to detect CDN regressions early"],"tags":["rust","zeroclaw","fal-ai","http-redirect","image-generation"],"backgroundTag":"too-many-redirects","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}