{"record":{"id":"17ffbe8eb427c284","repo":"chroma-core/chroma","slug":"failed-to-convert-image-numpy-array-to-base64-data","errorCode":null,"errorMessage":"Failed to convert image numpy array to base64 data URI: {e}","messagePattern":"Failed to convert image numpy array to base64 data URI: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/utils/embedding_functions/cohere_embedding_function.py","lineNumber":105,"sourceCode":"                    raise ValueError(\n                        f\"Expected image input to be a numpy array, got {type(image_np)}\"\n                    )\n\n                try:\n                    pil_image = self._PILImage.fromarray(image_np)\n\n                    buffer = io.BytesIO()\n                    pil_image.save(buffer, format=\"PNG\")\n                    img_bytes = buffer.getvalue()\n\n                    # Encode bytes to base64 string\n                    base64_string = base64.b64encode(img_bytes).decode(\"utf-8\")\n\n                    data_uri = f\"data:image/png;base64,{base64_string}\"\n                    base64_images.append(data_uri)\n\n                except Exception as e:\n                    raise ValueError(\n                        f\"Failed to convert image numpy array to base64 data URI: {e}\"\n                    ) from e\n\n            return [\n                np.array(embeddings, dtype=np.float32)\n                for embeddings in self.client.embed(\n                    images=base64_images,\n                    model=self.model_name,\n                    input_type=\"image\",\n                ).embeddings\n            ]\n        else:\n            # Check if it's a mix or neither\n            has_texts = any(is_document(item) for item in input)\n            has_images = any(is_image(item) for item in input)\n            if has_texts and has_images:\n                raise ValueError(\n                    \"Input contains a mix of text documents and images, which is not supported. Provide either all texts or all images.\"","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/utils/embedding_functions/cohere_embedding_function.py#L87-L123","documentation":"Each image ndarray goes through PIL.Image.fromarray(...), PNG save, and base64 encoding into a data:image/png;base64 URI; any exception in that chain is re-raised as this ValueError with the original error text appended after the colon. The usual culprit is an array PIL cannot interpret: float dtype (e.g. normalized 0..1 values), channel-first (3, H, W) shape, or an unsupported channel count.","triggerScenarios":"ef([np.random.rand(224, 224, 3)]) with float64 dtype; torchvision output transposed to (3, H, W); uint16/float32 arrays from scientific imaging; non-contiguous views that fromarray rejects.","commonSituations":"Feeding normalized tensors straight from a preprocessing pipeline; channel-first arrays from PyTorch models; cv2-loaded BGR or grayscale arrays without conversion/reshape.","solutions":["Read the {e} suffix - it carries PIL's original message ('Cannot handle this data type', 'not enough image data', etc.) and pinpoints the bad property.","Convert to uint8 HWC: for CHW float input use arr = (np.clip(arr, 0, 1) * 255).astype(np.uint8).transpose(1, 2, 0).","For cv2 images, convert BGR to RGB before embedding.","In batch jobs, wrap per-image encoding in try/except to skip and log corrupt frames instead of failing the batch."],"exampleFix":"# before\narr = np.random.rand(3, 224, 224).astype(np.float32)  # CHW, float\nef([arr])  # ValueError: Failed to convert image numpy array to base64 data URI\n\n# after\narr = np.transpose(arr, (1, 2, 0))  # HWC\narr = (np.clip(arr, 0, 1) * 255).astype(np.uint8)\nef([arr])","handlingStrategy":"try-catch","validationCode":"import numpy as np\n\ndef pil_encodable(a: np.ndarray) -> bool:\n    return a.dtype == np.uint8 and a.ndim == 3 and a.shape[2] in (3, 4)\n\nif not all(pil_encodable(x) for x in images):\n    images = [(np.clip(x, 0, 1) * 255).astype(np.uint8) if x.dtype != np.uint8 else x for x in images]","typeGuard":null,"tryCatchPattern":"for img in images:\n    try:\n        emb = ef([img])\n    except ValueError as e:\n        if 'base64 data URI' in str(e):\n            logger.warning('unencodable image skipped: %s', e)  # PIL suffix says what is wrong\n            continue\n        raise","preventionTips":["Standardize on uint8 (H, W, 3|4) arrays before the EF sees them.","Convert CHW/torch output with .transpose(1, 2, 0) and floats with (x * 255).astype(np.uint8).","Read the PIL error suffix in the message - it names the exact property PIL rejected.","In batch jobs, encode per-image with try/except to skip corrupt frames."],"tags":["chroma","cohere","multimodal","pillow","numpy","image-encoding"],"backgroundTag":"image-encoding-failure","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}