BerriAI/litellm · error · ValueError

Unsupported image type: {type(image)}. Expected bytes, str (

Error message

Unsupported image type: {type(image)}. Expected bytes, str (URL or file path), or file-like object.

What it means

_read_image_bytes accepts only three shapes: bytes, URL-prefixed strings (plus one-level lists of them), and objects with a .read() method. Any other type — int, dict, None, PIL.Image, numpy array, pathlib.Path — falls to the final else and raises ValueError naming the received type. This is a client-side argument-type failure raised before any HTTP traffic.

Source

Thrown at litellm/llms/black_forest_labs/image_edit/transformation.py:226

                response: Final = safe_get(litellm.module_level_client, image, timeout=60.0)
                response.raise_for_status()
                return response.content
            else:
                raise ValueError(
                    "Unsupported image input: plain string values that are not URLs are not accepted. "
                    "Provide image bytes or a file-like object."
                )
        elif hasattr(image, "read"):
            # File-like object
            pos: Final = getattr(image, "tell", lambda: 0)()
            if hasattr(image, "seek"):
                image.seek(0)
            data: Final = image.read()
            if hasattr(image, "seek"):
                image.seek(pos)
            return data
        else:
            raise ValueError(
                f"Unsupported image type: {type(image)}. Expected bytes, str (URL or file path), or file-like object."
            )

    def transform_image_edit_request(
        self,
        model: str,
        prompt: str | None,
        image: FileTypes | None,
        image_edit_optional_request_params: dict,
        litellm_params: GenericLiteLLMParams,
        headers: dict,
    ) -> tuple[dict, RequestFiles]:
        """
        Transform OpenAI-style request to Black Forest Labs request format.

        BFL uses JSON body with base64-encoded images, not multipart/form-data.
        """
        # Read and encode image

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Convert before calling: PIL -> io.BytesIO via img.save(buf, format='PNG'); numpy -> img.tobytes(); Path -> path.read_bytes().
  2. Always pass one of: bytes, https URL string, or an open binary file object.
  3. Assert the type in your own wrapper so bad values fail loudly at your boundary, not inside LiteLLM.

Example fix

# before
litellm.image_edit(model=..., image=pil_img, prompt="...")

# after
import io
buf = io.BytesIO(); pil_img.save(buf, format="PNG")
litellm.image_edit(model=..., image=buf.getvalue(), prompt="...")
Defensive patterns

Strategy: type-guard

Validate before calling

import io

def coerce_image(x):
    if hasattr(x, "read"): return x
    if isinstance(x, bytes): return x
    if isinstance(x, str) and x.startswith(("http://","https://")): return x
    if x.__class__.__name__ == "PngImagePlugin" or hasattr(x, "save"):
        buf = io.BytesIO(); x.save(buf, format="PNG"); return buf.getvalue()
    if hasattr(x, "tobytes"): return x.tobytes()
    raise TypeError(f"cannot coerce {type(x)} to BFL image")

Type guard

from typing import Any

def is_bfl_supported_image(x: Any) -> bool:
    return (
        isinstance(x, bytes)
        or (isinstance(x, str) and x.startswith(("http://", "https://")))
        or hasattr(x, "read")
        or (isinstance(x, list) and x and is_bfl_supported_image(x[0]))
    )

Try / catch

null

Prevention

When it happens

Trigger: Passing image as a PIL.Image.Image, numpy.ndarray, pathlib.Path, dict, or None to image_edit with a black_forest_labs model.

Common situations: Feeding the output of an upstream Python imaging pipeline (PIL/numpy) straight into image_edit; passing Path objects since they feel string-like; forgetting the image argument entirely in a wrapper function (None).

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/1c5fd484f7d46bbb. Report an issue: GitHub.