BerriAI/litellm · error · ValueError

Unsupported image type for Vertex AI Gemini image edit.

Error message

Unsupported image type for Vertex AI Gemini image edit.

What it means

The Gemini image-edit byte reader (_read_all_bytes in vertex_gemini_transformation.py:257) accepts only three shapes: raw bytes, io.BytesIO, and io.BufferedReader (a file opened in binary mode). Everything else — str (path or base64), pathlib.Path, the OpenAI-style FileTypes tuple ('cat.png', b'...'), PIL images, text-mode file handles — falls through to this ValueError. Unlike the Imagen variant, it does not unwrap tuples, dicts, or nested lists.

Source

Thrown at litellm/llms/vertex_ai/image_edit/vertex_gemini_transformation.py:272

        return inline_parts

    def _read_all_bytes(self, image: FileTypes) -> bytes:
        if isinstance(image, bytes):
            return image
        if isinstance(image, BytesIO):
            current_pos = image.tell()
            image.seek(0)
            data = image.read()
            image.seek(current_pos)
            return data
        if isinstance(image, BufferedReader):
            current_pos = image.tell()
            image.seek(0)
            data = image.read()
            image.seek(current_pos)
            return data
        raise ValueError("Unsupported image type for Vertex AI Gemini image edit.")

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Open the file in binary mode: open('cat.png', 'rb') yields a BufferedReader, which is accepted
  2. Pass raw bytes or io.BytesIO(bytes) for in-memory images
  3. Convert pathlib.Path via Path('cat.png').read_bytes()
  4. base64-decode strings first: base64.b64decode(data_uri.split(',')[1])

Example fix

# before
resp = litellm.image_edit(
    model='vertex_ai/gemini-2.5-flash-image',
    prompt='add a hat',
    image='cat.png',  # str path -> raises
)

# after
with open('cat.png', 'rb') as f:  # BufferedReader
    resp = litellm.image_edit(
        model='vertex_ai/gemini-2.5-flash-image',
        prompt='add a hat',
        image=f,
    )
Defensive patterns

Strategy: type-guard

Validate before calling

from io import BytesIO, BufferedReader

def is_gemini_edit_compatible(img) -> bool:
    return isinstance(img, (bytes, BytesIO, BufferedReader))

assert is_gemini_edit_compatible(image), 'provide bytes, BytesIO, or a file opened in rb mode'

Type guard

from io import BytesIO, BufferedReader
from typing import Any

def is_readable_image(img: Any) -> bool:
    """Narrow to types the Vertex Gemini image-edit reader accepts."""
    return isinstance(img, (bytes, BytesIO, BufferedReader))

Try / catch

try:
    resp = litellm.image_edit(model='vertex_ai/gemini-2.5-flash-image', prompt=p, image=image)
except ValueError as e:
    if 'Unsupported image type' in str(e):
        raise ValueError('Convert image to bytes/BytesIO/binary file before editing') from e
    raise

Prevention

When it happens

Trigger: image=open('cat.png', 'r') (TextIOWrapper, not BufferedReader); image='cat.png' or a base64 string; image=Path('cat.png'); image=('cat.png', b'...') tuple form; passing a list wrapped in a tuple so the whole tuple reaches _read_all_bytes.

Common situations: Reusing code built for requests/httpx multipart files= tuples; passing base64 data-URI strings received from a JSON API; opening files without 'b' mode on Windows or after refactoring; passing pathlib.Path objects from modern scripts.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/dd4b46b2061fe62c. Report an issue: GitHub.