{"record":{"id":"34e3b58ca5d60a54","repo":"zeroclaw-labs/zeroclaw","slug":"all-image-generation-model-providers-failed-and-fa","errorCode":null,"errorMessage":"All image generation model_providers failed and fallback_card is disabled","messagePattern":"All image generation model_providers failed and fallback_card is disabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/linkedin_client.rs","lineNumber":893,"sourceCode":"                    ::zeroclaw_log::record!(WARN, ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note).with_outcome(::zeroclaw_log::EventOutcome::Unknown).with_attrs(::serde_json::json!({\"error\": format!(\"{}\", e), \"provider_name\": provider_name})), \"Image model_provider '' failed\");\n                }\n            }\n        }\n\n        // All AI model_providers failed — try SVG fallback\n        if self.config.fallback_card {\n            let svg_path = image_dir.join(format!(\"{base_name}.svg\"));\n            let svg_content = Self::generate_fallback_card(prompt, &self.config.card_accent_color);\n            tokio::fs::write(&svg_path, &svg_content).await?;\n            ::zeroclaw_log::record!(\n                INFO,\n                ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note),\n                &format!(\"Fallback SVG card generated: {}\", svg_path.display())\n            );\n            return Ok(svg_path);\n        }\n\n        anyhow::bail!(\"All image generation model_providers failed and fallback_card is disabled\")\n    }\n\n    /// Read an env var value from the workspace .env file (same format as LinkedInClient).\n    async fn read_env_var(workspace_dir: &Path, var_name: &str) -> anyhow::Result<String> {\n        let env_path = workspace_dir.join(\".env\");\n        let content = tokio::fs::read_to_string(&env_path)\n            .await\n            .with_context(|| format!(\"Failed to read {}\", env_path.display()))?;\n\n        for line in content.lines() {\n            let line = line.trim();\n            if line.starts_with('#') || line.is_empty() {\n                continue;\n            }\n            let line = line.strip_prefix(\"export \").map(str::trim).unwrap_or(line);\n            if let Some((key, value)) = line.split_once('=')\n                && key.trim() == var_name\n            {","sourceCodeStart":875,"sourceCodeEnd":911,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/linkedin_client.rs#L875-L911","documentation":"ImageGenerator::generate walks the configured providers list (stability, imagen, dalle, flux) in order; every provider either failed (missing key in .env, HTTP error, exhausted credits) or was skipped as an unknown name. With fallback_card disabled there is no branded-SVG fallback, so the whole operation bails. Each per-provider cause was already logged as a WARN 'Image model_provider failed' event with the provider name and error.","triggerScenarios":"No *_API_KEY entries in the workspace .env for any configured provider; keys present but every request failed (401/403 expired key, 429 quota, blocked egress); providers list empty or containing only misspelled names, which are skipped with a WARN and never tried.","commonSituations":"New workspaces whose .env was never filled in; expired billing on the single configured provider; names like 'dalle3' instead of 'dalle' in the image providers config.","solutions":["Check the preceding WARN logs — each provider failure records its error and provider_name, distinguishing missing-key from API failure","Set at least one provider key in the workspace .env, matching the env var name configured in that provider's api_key_env","Enable fallback_card in the LinkedIn image config so a branded SVG card is produced instead of an error","Verify provider names are exactly stability, imagen, dalle, or flux"],"exampleFix":"# before (config)\nfallback_card = false\nproviders = [\"dalle\"]\n# .env has no OPENAI_API_KEY\n\n# after\nfallback_card = true\nproviders = [\"dalle\", \"stability\"]\n# .env\nOPENAI_API_KEY=sk-...","handlingStrategy":"fallback","validationCode":"fn any_provider_key(dir: &Path, cfg: &LinkedInImageConfig) -> bool {\n    let names: Vec<&str> = vec![\n        &cfg.stability.api_key_env, &cfg.imagen.api_key_env,\n        /* dalle + flux api_key_env */\n    ];\n    names.iter().any(|k| env_has_key(dir, k))\n}\n\nanyhow::ensure!(\n    any_provider_key(&workspace_dir, &image_config) || image_config.fallback_card,\n    \"image generation will always fail: no provider key and fallback_card disabled\"\n);","typeGuard":null,"tryCatchPattern":"Catch the generate() error and degrade gracefully: post text-only, or produce your own placeholder asset — the library has no further fallback once fallback_card is off.","preventionTips":["Keep at least two providers in the providers list so one bad key does not sink the post","Enable fallback_card for unattended scheduled posting","Alert on the WARN 'Image model_provider failed' logs before the hard failure appears"],"tags":["image-generation","configuration","providers","fallback"],"backgroundTag":"all-providers-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}