BerriAI/litellm · error · Exception
Image url not in expected format. Example Expected input - "
Error message
Image url not in expected format. Example Expected input - "image_url": "data:image/jpeg;base64,{base64_image}". What it means
Raised in convert_url_to_base64: LiteLLM tried to normalize an image_url into base64 data and every path failed. The URL was not a fetchable http(s) image (fetch errors are re-raised as-is) and the string did not contain the expected 'data:image/...;base64,' structure, so the fallback parse threw and this generic Exception wraps it. The message shows the expected data-URI form.
Source
Thrown at litellm/litellm_core_utils/prompt_templates/factory.py:183
return prompt
def convert_to_ollama_image(openai_image_url: str):
try:
if openai_image_url.startswith("http"):
openai_image_url = convert_url_to_base64(url=openai_image_url)
if openai_image_url.startswith("data:image/"):
# Extract the base64 image data
base64_data = openai_image_url.split("data:image/")[1].split(";base64,")[1]
else:
base64_data = openai_image_url
return base64_data
except Exception as e:
if "Error: Unable to fetch image from URL" in str(e):
raise e
raise Exception(
"""Image url not in expected format. Example Expected input - "image_url": "data:image/jpeg;base64,{base64_image}". """
)
def _handle_ollama_system_message(messages: list, prompt: str, msg_i: int) -> tuple[str, int]:
system_content_str = ""
## MERGE CONSECUTIVE SYSTEM CONTENT ##
while msg_i < len(messages) and messages[msg_i]["role"] == "system":
msg_content = convert_content_list_to_str(messages[msg_i])
system_content_str += msg_content
msg_i += 1
return system_content_str, msg_i
def ollama_pt(
model: str, messages: listView on GitHub (pinned to 6c2dcb801b)
Solutions
- Use a proper data URI: "data:image/jpeg;base64,<base64_data>"
- If using an http(s) URL, verify it returns 200 with an image content-type (curl -I) and is reachable from where LiteLLM runs
- For local files, base64-encode them yourself into a data URI instead of passing a path
- For cloud-store images, download the bytes first (boto3/gcs client) then inline them as base64
Example fix
# before
msg = {"role": "user", "content": [
{"type": "image_url", "image_url": {"url": "/tmp/cat.png"}}
]}
# after
import base64, mimetypes
path = "/tmp/cat.png"
b64 = base64.b64encode(open(path, "rb").read()).decode()
mime = mimetypes.guess_type(path)[0] or "image/png"
msg = {"role": "user", "content": [
{"type": "image_url", "image_url": {"url": f"data:{mime};base64,{b64}"}}
]} Defensive patterns
Strategy: validation
Validate before calling
import re
DATA_URI_RE = re.compile(r"^data:image/(?:jpeg|png|gif|webp);base64,[A-Za-z0-9+/=\s]+$")
def is_usable_image_url(u: str) -> bool:
return u.startswith(("http://", "https://")) or bool(DATA_URI_RE.match(u))
for block in content:
if block.get("type") == "image_url" and not is_usable_image_url(block["image_url"]["url"]):
raise ValueError(f"bad image_url: {block['image_url']['url'][:50]}...") Type guard
import re
from typing import Any
_DATA_URI = re.compile(r"^data:image/(?:jpeg|png|gif|webp);base64,[A-Za-z0-9+/=]+$")
def is_valid_image_url(v: Any) -> bool:
return isinstance(v, str) and (v.startswith(("http://", "https://")) or bool(_DATA_URI.match(v))) Try / catch
try:
litellm.completion(model=model, messages=messages)
except Exception as e:
if "Image url not in expected format" in str(e):
# re-encode the image locally as a data URI and retry once
b64 = base64.b64encode(fetch(image_path).content).decode()
messages = inject_data_uri(messages, f"data:image/png;base64,{b64}")
litellm.completion(model=model, messages=messages)
else:
raise Prevention
- Always send images as data URIs you generated yourself or verified http(s) URLs
- curl -I any image URL once before shipping to confirm image/* content-type
- Base64-encode local files; never pass filesystem paths
When it happens
Trigger: Passing a vision message where image_url.url is a relative path, an S3/gs:// URI, a data URI missing ';base64,' or with a malformed prefix (e.g. 'data:image/jpeg, ...'), or a URL that returns HTML/non-image bytes; occurs on models whose handler converts images server-side (Ollama, Anthropic, Bedrock image paths).
Common situations: Using presigned S3/GCS URLs that expired or redirect to a login page; hand-building data URIs with typos; local file paths ('/tmp/img.png') instead of http URLs or base64 data URIs; providers that cannot fetch intranet URLs from LiteLLM's host.
Related errors
- Image url not in expected format. Example Expected input - "
- gemini image conversion failed please run `pip install Pillo
- Invalid image URL: {content_image_url}
- input is required
- Unable to determine content type from URL: {url}. Response c
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/6d9d6debaea54423.
Report an issue: GitHub.