BerriAI/litellm · error · Exception

image conversion failed please run `pip install Pillow`

Error message

image conversion failed please run `pip install Pillow`

What it means

Raised by _load_image_from_url when 'from PIL import Image' fails: Pillow is not installed in the LiteLLM process, and this Gemini image path needs it to open/inspect fetched image bytes. The message is the library's install hint. Note the URL-fetch step never runs — this is purely a missing-dependency error.

Source

Thrown at litellm/litellm_core_utils/prompt_templates/factory.py:3178

    for idx, message in enumerate(messages):
        if message["role"] == "user":
            prompt += f"{AmazonTitanConstants.HUMAN_PROMPT.value}{message['content']}"
        elif message["role"] == "system":
            prompt += f"{AmazonTitanConstants.HUMAN_PROMPT.value}<admin>{message['content']}</admin>"
        else:
            prompt += f"{AmazonTitanConstants.AI_PROMPT.value}{message['content']}"
        if idx == 0 and message["role"] == "assistant":  # ensure the prompt always starts with `\n\nHuman: `
            prompt = f"{AmazonTitanConstants.HUMAN_PROMPT.value}" + prompt
    if messages[-1]["role"] != "assistant":
        prompt += f"{AmazonTitanConstants.AI_PROMPT.value}"
    return prompt


def _load_image_from_url(image_url):
    try:
        from PIL import Image
    except Exception:
        raise Exception("image conversion failed please run `pip install Pillow`")
    from io import BytesIO

    try:
        # Send a GET request to the image URL
        client: Final = HTTPHandler(concurrent_limit=1)
        response: Final[httpx.Response] = safe_get(client, image_url)
        response.raise_for_status()  # Raise an exception for HTTP errors

        # Check the response's content type to ensure it is an image
        content_type: Final = response.headers.get("content-type")
        if not content_type or "image" not in content_type:
            raise ValueError(f"URL does not point to a valid image (content-type: {content_type})")

        # Load the image from the response content
        return Image.open(BytesIO(response.content))

    except Exception as e:
        raise e

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. pip install Pillow (and add it to your requirements/pyproject so it persists)
  2. If you cannot install it, avoid the Pillow path: pass images as data URIs (data:image/...;base64,...) so no local image opening is needed
  3. Rebuild your deployment image with Pillow included

Example fix

# before: Dockerfile
RUN pip install litellm
# at runtime: Exception 'image conversion failed please run `pip install Pillow`'

# after
RUN pip install litellm Pillow
Defensive patterns

Strategy: validation

Validate before calling

def pillow_available() -> bool:
    try:
        import PIL  # noqa: F401
        return True
    except ImportError:
        return False

assert pillow_available(), "pip install Pillow before sending image URLs to Gemini"

Prevention

When it happens

Trigger: Sending an https:// image URL to a Gemini conversion path that calls _load_image_from_url in an environment where Pillow is absent (slim Docker images, 'liteellm' installed without the imaging extras, some serverless deployments).

Common situations: Custom Dockerfiles that pip install litellm but prune Pillow; CI environments running integration tests with vision URLs; upgrading deployments where the previous image happened to include Pillow transitively.

Related errors


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