iflytek/astron-agent · error · Exception
Failed to download image from
Error message
Failed to download image from {image_url} What it means
Raised in BaseNode._assemble_messages when downloading an image for an image-understanding LLM call fails: requests.get(image_url) returned a non-200 status. This is a plain Exception (not CustomException) because image download is considered an unexpected runtime failure while assembling chat messages.
Solutions
- Verify the image URL is reachable (curl it) and re-upload/re-generate a fresh presigned URL if expired
- Ensure the image is publicly accessible from the workflow service or pass credentials appropriately
- Fix the upstream node/variable that produced the wrong image URL
- Add retry with backoff for transient 5xx and pre-validate URLs before executing the node
Example fix
// before
image_url = "https://minio/bucket/old.png?expires=..." // expired
// after
image_url = refresh_presigned_url("bucket", "old.png") Defensive patterns
Strategy: try-catch
Validate before calling
import requests
def image_url_reachable(url: str) -> bool:
try:
return requests.head(url, timeout=5).status_code == 200
except requests.RequestException:
return False Try / catch
try:
await node._chat_with_llm(...)
except Exception as e:
if str(e).startswith("Failed to download image from"):
log.error("image unavailable: %s", e)
return fallback_text_only_response()
raise Prevention
- Use short-lived presigned URLs generated at execution time, not stored ones
- Pre-validate image URLs (HEAD request) before running image-understanding nodes
- Ensure the workflow service can reach object storage over the network
When it happens
Trigger: Calling _chat_with_llm on a node configured with an image_url where the URL returns 404/403/5xx, points to an expired signed URL, or the storage object was deleted.
Common situations: Expired MinIO/S3 presigned URLs saved in old workflow runs; private images requiring auth headers that requests.get does not send; mistyped image URLs in node inputs; network/DNS failures inside the cluster.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- PERSONALITY_AI_GENERATE_ERROR
- sandbox-exec failed: HTTP
- Skill resource download failed: HTTP
- OPEN_AI_API_ERROR
- MODEL_CHECK_FAILED
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/a82fdddfca067a3e.
Report an issue: GitHub.
Appendix: source
Thrown at core/workflow/engine/nodes/base_node.py:1202
# Handle images in history
if payload_comp_history and payload_comp_history[0].content_type == "image":
if self.source == ModelProviderEnum.OPENAI.value:
payload_comp_history.pop(0)
if self.source == ModelProviderEnum.XINGHUO.value:
image_models = os.getenv(
"SPARK_IMAGE_MODEL_DOMAIN", "image,imagev3"
).split(",")
if self.domain in image_models:
if not image_url:
image_url = payload_comp_history[0].content
payload_comp_history.pop(0)
# If it's an image understanding model, reserve the first position in array for image
if image_url:
import requests # type: ignore
image_response = requests.get(image_url)
if image_response.status_code != 200:
raise Exception(f"Failed to download image from {image_url}")
image_msg = {
"role": "user",
"content": str(
base64.b64encode(image_response.content).decode("utf-8")
),
"content_type": "image",
}
await span_context.add_info_events_async({"image": str(image_url)})
# Don't upload base64
if image_msg:
await span_context.add_info_events_async(
{"user_message": json.dumps(user_message[1:], ensure_ascii=False)}
)
else:
await span_context.add_info_events_async(
{"user_message": json.dumps(user_message, ensure_ascii=False)}
)
history = [View on GitHub (pinned to 5e758547a8)