{"record":{"id":"84f71e402af376d8","repo":"BerriAI/litellm","slug":"gemini-image-conversion-failed-please-run-pip-ins","errorCode":null,"errorMessage":"gemini image conversion failed please run `pip install Pillow`","messagePattern":"gemini 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":3241,"sourceCode":"                    if isinstance(element, dict):\n                        if element[\"type\"] == \"text\":\n                            prompt += element[\"text\"]\n                        elif element[\"type\"] == \"image_url\":\n                            image_url = element[\"image_url\"][\"url\"]\n                            images.append(image_url)\n        # processing images passed to gemini\n        processed_images: Final = []\n        for img in images:\n            if \"https:/\" in img:\n                # Case 1: Image from URL\n                image = _load_image_from_url(img)\n                processed_images.append(image)\n\n            else:\n                try:\n                    from PIL import Image\n                except Exception:\n                    raise Exception(\"gemini image conversion failed please run `pip install Pillow`\")\n\n                if \"base64\" in img:\n                    # Case 2: Base64 image data\n                    import base64\n                    import io\n\n                    # Extract the base64 image data\n                    base64_data = img.split(\"base64,\")[1]\n\n                    # Decode the base64 image data\n                    image_data = base64.b64decode(base64_data)\n\n                    # Load the image from the decoded data\n                    image = Image.open(io.BytesIO(image_data))\n                else:\n                    # Case 3: Image filepath (e.g. temp.jpeg) given\n                    image = Image.open(img)\n                processed_images.append(image)","sourceCodeStart":3223,"sourceCodeEnd":3259,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/prompt_templates/factory.py#L3223-L3259","documentation":"In the Gemini vision conversion for non-URL images: the branch that handles base64/local images does 'from PIL import Image' and the import failed, so LiteLLM raises with the Pillow install hint. It fires for image strings containing 'base64' (or local references) rather than https:// URLs.","triggerScenarios":"Passing base64 data-URI images to the Gemini path that decodes and re-encodes them via Pillow when Pillow is not installed; slim containers or minimal installs lacking PIL.","commonSituations":"Same as 835: pruned Docker images, CI without imaging deps, serverless bundles that strip Pillow; appears only when the image is not a plain https URL.","solutions":["pip install Pillow and pin it in your dependency manifest","Alternatively pass a clean data URI in a form that needs no re-encoding (or an https URL), avoiding the Pillow branch","Rebuild the deployment image with imaging extras (e.g. pip install 'litellm[extra_proxy]' or add Pillow explicitly)"],"exampleFix":"# before\n$ pip install litellm  # no Pillow\nlitellm.completion(model=\"gemini/gemini-1.5-flash\", messages=[..., {\"type\": \"image_url\", \"image_url\": {\"url\": \"data:image/png;base64,...\"}}])\n\n# after\n$ pip install litellm Pillow\n# same call now succeeds","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 base64 images to Gemini\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install Pillow wherever LiteLLM runs vision workloads","Pin Pillow in requirements/pyproject","Test the base64 image path in staging, not just URL images"],"tags":["dependencies","pillow","gemini","vision","base64"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}