zeroclaw-labs/zeroclaw · error · anyhow::Error
Failed to download Flux image from {image_url}
Error message
Failed to download Flux image from {image_url} What it means
try_flux's generation request succeeded and returned an image URL, but the follow-up GET that downloads the bytes from /images/0/url came back non-success. The failure is the asset fetch, not generation: typically the signed URL expired, the CDN was unreachable, or an egress path allows the API host but not the image host.
Source
Thrown at crates/zeroclaw-tools/src/linkedin_client.rs:1167
let json: serde_json::Value = resp.json().await?;
let image_url = json
.pointer("/images/0/url")
.and_then(|v| v.as_str())
.ok_or_else(|| {
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({"image_provider": "flux"})),
"linkedin_client: Flux response missing image URL"
);
anyhow::Error::msg("No image URL in Flux response")
})?;
// Download the image from the returned URL
let img_resp = client.get(image_url).send().await?;
if !img_resp.status().is_success() {
anyhow::bail!("Failed to download Flux image from {image_url}");
}
let bytes = img_resp.bytes().await?;
let path = output_dir.join(format!("{base_name}_flux.png"));
tokio::fs::write(&path, &bytes).await?;
Ok(path)
}
// ── SVG Fallback Card ───────────────────────────────────────
/// Generate a branded SVG text card with the post title on a gradient background.
pub fn generate_fallback_card(title: &str, accent_color: &str) -> String {
// Truncate title to ~80 bytes for clean display without splitting UTF-8.
let display_title = if title.len() > 80 {
let end = crate::util_helpers::floor_char_boundary(title, 77);
format!("{}...", &title[..end])
} else {
title.to_string()
};View on GitHub (pinned to 88bb9c8533)
Solutions
- Regenerate (call generate again) to obtain a fresh signed URL — do not retry the stale one
- Download immediately after generation and never persist the URL for later use
- Check proxy/egress rules cover the image host, not just the API endpoint
Example fix
// before: reusing a saved URL
let img = client.get(saved_flux_url).send().await?;
// after: re-generate to get a fresh signed URL
let path = match generator.generate(prompt).await {
Ok(p) => p,
Err(e) if e.to_string().contains("Failed to download Flux image") => {
generator.generate(prompt).await? // fresh URL
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: retry
Try / catch
Catch errors containing 'Failed to download Flux image' and re-run generate() once to obtain a fresh signed URL; do not retry the stale URL — expiry makes it permanently invalid.
Prevention
- Download immediately after generation; never persist Flux image URLs
- Ensure egress rules cover the image CDN host, not just the API host
- Keep another provider configured so a download failure can be bypassed by a provider that returns inline base64
When it happens
Trigger: Delay between generation and download long enough for the signed URL to expire (4xx); CDN/network failure (5xx); proxy or firewall rules that permit the Flux API domain but block the image host.
Common situations: Saving URLs and downloading them later instead of immediately; corporate proxies with domain allowlists; slow networks causing the download to start after the URL's TTL.
Related errors
- Generated image download failed with HTTP {}
- channel does not support room creation
- elicitation returned unknown choice const: {s}
- purge_namespace not supported by this memory backend
- IRC connection closed by server
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/d2bb2237364d13be.
Report an issue: GitHub.