sigoden/aichat · error
The model does not support network images
Error message
The model does not support network images: {:?} What it means
Thrown by gemini_build_chat_completions_body in src/client/vertexai.rs:384 when a chat completions request includes image URLs that are remote http(s) URLs rather than base64 data URLs. The Gemini/Vertex AI body builder only converts `data:<mime>;base64,<data>` image URLs into inline_data parts; any other URL is collected into network_image_urls and the request is rejected before it is sent. The library does this because the Gemini generateContent endpoint it targets does not accept remote image URLs in message parts.
Solutions
- Download the image and inline it as a base64 data URL, e.g. "data:image/jpeg;base64,<base64 bytes>", before building the message.
- Use a helper to fetch the URL, detect its MIME type, and base64-encode the bytes into the ImageUrl `url` field.
- If the images are stored on GCS, switch to a Gemini file/inline reference supported by the API instead of a public https URL.
- Strip or replace image parts with a text description when the target model doesn't support vision.
Example fix
// before
MessageContentPart::ImageUrl { image_url: ImageUrl { url: "https://example.com/cat.jpg".into() } }
// after
let bytes = reqwest::get("https://example.com/cat.jpg").await?.bytes().await?;
let data_url = format!("data:image/jpeg;base64,{}", base64::engine::general_purpose::STANDARD.encode(&bytes));
MessageContentPart::ImageUrl { image_url: ImageUrl { url: data_url } } Defensive patterns
Strategy: validation
Validate before calling
fn assert_no_network_images(messages: &[Message]) -> Result<(), Vec<String>> {
let mut bad = vec![];
for msg in messages {
if let MessageContent::Array(parts) = &msg.content {
for p in parts {
if let MessageContentPart::ImageUrl { image_url: ImageUrl { url } } = p {
if !url.starts_with("data:") {
bad.push(url.clone());
}
}
}
}
}
if bad.is_empty() { Ok(()) } else { Err(bad) }
} Type guard
fn is_inline_image_url(url: &str) -> bool {
url.starts_with("data:") && url.contains(";base64,")
} Try / catch
let body = match gemini_build_chat_completions_body(data, &model) {
Ok(b) => b,
Err(e) if e.to_string().starts_with("The model does not support network images") => {
// convert URLs to base64 data URLs and rebuild
let data = inline_all_images(data).await?;
gemini_build_chat_completions_body(data, &model)?
}
Err(e) => return Err(e.into()),
}; Prevention
- Always convert remote image URLs to base64 data URLs before sending to Gemini/Vertex AI models.
- Write a preprocessing step in your pipeline that fetches, MIME-detects, and inlines every image.
- Remember the OpenAI API accepts https image URLs but this Gemini client does not — audit ported code.
- Store images locally or as data URLs at ingest time so downstream calls never see raw URLs.
- Unit-test message builders with a mix of data: and https: image parts to catch regressions.
When it happens
Trigger: Calling chat_completions on a Vertex AI/Gemini model with a message content part of type ImageUrl whose url is a network URL (e.g. "https://example.com/cat.jpg") instead of a base64 data URL like "data:image/jpeg;base64,...". Every non-data: URL in the request causes this bail, listing all offending URLs.
Common situations: Porting code from OpenAI-style clients (which accept https image URLs) to this Vertex AI client; loading image URLs directly from a database or user input without downloading/encoding them; forgetting the multipart/inline image step in an image-captioning pipeline.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Invalid response data
- The model does not support network images
- The model does not support network images
- {err_msg}
- Invalid response data
AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09).
Data as JSON: /api/errors/2e013984b85e094b.
Report an issue: GitHub.
Appendix: source
Thrown at src/client/vertexai.rs:384
"name": tool_result.call.name,
"response": {
"name": tool_result.call.name,
"content": tool_result.output,
}
}
})
}).collect();
vec![
json!({ "role": "model", "parts": model_parts }),
json!({ "role": "function", "parts": function_parts }),
]
}
}
})
.collect();
if !network_image_urls.is_empty() {
bail!(
"The model does not support network images: {:?}",
network_image_urls
);
}
let mut body = json!({ "contents": contents, "generationConfig": {} });
if let Some(v) = system_message {
body["systemInstruction"] = json!({ "parts": [{"text": v }] });
}
if let Some(v) = model.max_tokens_param() {
body["generationConfig"]["maxOutputTokens"] = v.into();
}
if let Some(v) = temperature {
body["generationConfig"]["temperature"] = v.into();
}
if let Some(v) = top_p {View on GitHub (pinned to 82976d349a)