{"record":{"id":"d6e4fc83a4bbb58b","repo":"chroma-core/chroma","slug":"the-pil-python-package-is-not-installed-please-in","errorCode":null,"errorMessage":"The PIL python package is not installed. Please install it with `pip install pillow`","messagePattern":"The PIL python package is not installed\\. Please install it with `pip install pillow`","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/utils/data_loaders.py","lineNumber":15,"sourceCode":"import importlib\nimport multiprocessing\nfrom typing import Optional, Sequence, List, Tuple\nimport numpy as np\nfrom chromadb.api.types import URI, DataLoader, Image, URIs\nfrom concurrent.futures import ThreadPoolExecutor\n\n\nclass ImageLoader(DataLoader[List[Optional[Image]]]):\n    def __init__(self, max_workers: int = multiprocessing.cpu_count()) -> None:\n        try:\n            self._PILImage = importlib.import_module(\"PIL.Image\")\n            self._max_workers = max_workers\n        except ImportError:\n            raise ValueError(\n                \"The PIL python package is not installed. Please install it with `pip install pillow`\"\n            )\n\n    def _load_image(self, uri: Optional[URI]) -> Optional[Image]:\n        return np.array(self._PILImage.open(uri)) if uri is not None else None\n\n    def __call__(self, uris: Sequence[Optional[URI]]) -> List[Optional[Image]]:\n        with ThreadPoolExecutor(max_workers=self._max_workers) as executor:\n            return list(executor.map(self._load_image, uris))\n\n\nclass ChromaLangchainPassthroughDataLoader(DataLoader[List[Optional[Image]]]):\n    # This is a simple pass through data loader that just returns the input data with \"images\"\n    # flag which lets the langchain embedding function know that the data is image uris\n    def __call__(self, uris: URIs) -> Tuple[str, URIs]:  # type: ignore\n        return (\"images\", uris)\n","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/utils/data_loaders.py#L1-L32","documentation":"ImageLoader is chromadb's DataLoader that turns image URIs into numpy arrays, and it does so through Pillow: its constructor calls importlib.import_module(\"PIL.Image\") and, if that raises ImportError, re-raises it as this ValueError. Pillow is an optional dependency, so a plain `pip install chromadb` does not pull it in. The error surfaces at construction time, before any image is actually loaded.","triggerScenarios":"Instantiating chromadb.utils.data_loaders.ImageLoader() in an environment where pillow is not installed, typically to pass it as data_loader= to client.get_collection(), client.list_collections(), or to use include=[\"images\"] / add() with URIs on a multimodal collection.","commonSituations":"Fresh virtualenv or CI runner with only chromadb installed; slim Docker images (python:*-slim) that skip build deps; tutorials on multimodal collections that assume pillow is present but never list it in requirements.","solutions":["Install pillow in the active environment: pip install pillow (or add `pillow` to requirements.txt next to chromadb).","Verify the install lands in the interpreter you run: python -c \"import PIL; print(PIL.__version__)\".","If you do not actually need image decoding, drop ImageLoader entirely and stop requesting include=[\"images\"]."],"exampleFix":"# before: raises ValueError \"The PIL python package is not installed...\"\nfrom chromadb.utils.data_loaders import ImageLoader\nloader = ImageLoader()\n\n# after: install pillow first (pip install pillow), then\nfrom chromadb.utils.data_loaders import ImageLoader\nloader = ImageLoader()\ncol = client.get_collection(\"imgs\", embedding_function=ef, data_loader=loader)","handlingStrategy":"validation","validationCode":"import importlib.util\n\nif importlib.util.find_spec(\"PIL\") is None:\n    raise RuntimeError(\"pillow is required for ImageLoader; run: pip install pillow\")\n\nfrom chromadb.utils.data_loaders import ImageLoader\nloader = ImageLoader()","typeGuard":null,"tryCatchPattern":"from chromadb.utils.data_loaders import ImageLoader\ntry:\n    loader = ImageLoader()\nexcept ValueError as e:\n    if \"PIL\" in str(e):\n        raise RuntimeError(\"Install pillow to load images: pip install pillow\") from e\n    raise","preventionTips":["Add `pillow` to requirements.txt next to chromadb in any project using image URIs.","Run a find_spec dependency probe at application startup before creating clients.","In Docker, add an explicit `pip install pillow` layer and a smoke-import test in CI."],"tags":["python","pip","pillow","optional-dependency","image-loader","chromadb"],"backgroundTag":"missing-optional-dependency","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}