{"record":{"id":"4aa4946d677d7dfe","repo":"BerriAI/litellm","slug":"image-conversion-failed-please-run-pip-install-pi","errorCode":null,"errorMessage":"image conversion failed please run `pip install Pillow`","messagePattern":"image conversion failed please run `pip install Pillow`","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/prompt_templates/factory.py","lineNumber":3178,"sourceCode":"    for idx, message in enumerate(messages):\n        if message[\"role\"] == \"user\":\n            prompt += f\"{AmazonTitanConstants.HUMAN_PROMPT.value}{message['content']}\"\n        elif message[\"role\"] == \"system\":\n            prompt += f\"{AmazonTitanConstants.HUMAN_PROMPT.value}<admin>{message['content']}</admin>\"\n        else:\n            prompt += f\"{AmazonTitanConstants.AI_PROMPT.value}{message['content']}\"\n        if idx == 0 and message[\"role\"] == \"assistant\":  # ensure the prompt always starts with `\\n\\nHuman: `\n            prompt = f\"{AmazonTitanConstants.HUMAN_PROMPT.value}\" + prompt\n    if messages[-1][\"role\"] != \"assistant\":\n        prompt += f\"{AmazonTitanConstants.AI_PROMPT.value}\"\n    return prompt\n\n\ndef _load_image_from_url(image_url):\n    try:\n        from PIL import Image\n    except Exception:\n        raise Exception(\"image conversion failed please run `pip install Pillow`\")\n    from io import BytesIO\n\n    try:\n        # Send a GET request to the image URL\n        client: Final = HTTPHandler(concurrent_limit=1)\n        response: Final[httpx.Response] = safe_get(client, image_url)\n        response.raise_for_status()  # Raise an exception for HTTP errors\n\n        # Check the response's content type to ensure it is an image\n        content_type: Final = response.headers.get(\"content-type\")\n        if not content_type or \"image\" not in content_type:\n            raise ValueError(f\"URL does not point to a valid image (content-type: {content_type})\")\n\n        # Load the image from the response content\n        return Image.open(BytesIO(response.content))\n\n    except Exception as e:\n        raise e","sourceCodeStart":3160,"sourceCodeEnd":3196,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/prompt_templates/factory.py#L3160-L3196","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["pip install Pillow (and add it to your requirements/pyproject so it persists)","If you cannot install it, avoid the Pillow path: pass images as data URIs (data:image/...;base64,...) so no local image opening is needed","Rebuild your deployment image with Pillow included"],"exampleFix":"# before: Dockerfile\nRUN pip install litellm\n# at runtime: Exception 'image conversion failed please run `pip install Pillow`'\n\n# after\nRUN pip install litellm Pillow","handlingStrategy":"validation","validationCode":"def pillow_available() -> bool:\n    try:\n        import PIL  # noqa: F401\n        return True\n    except ImportError:\n        return False\n\nassert pillow_available(), \"pip install Pillow before sending image URLs to Gemini\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add Pillow to your deployment's dependency manifest","Smoke-test vision flows in CI (they catch missing imaging deps)","Prefer data URIs to avoid the Pillow-dependent URL path"],"tags":["dependencies","pillow","gemini","vision"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}