{"record":{"id":"e5ddcb747e7f611b","repo":"chroma-core/chroma","slug":"failed-to-convert-image-numpy-array-to-base64-data-e5ddcb","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/jina_embedding_function.py","lineNumber":135,"sourceCode":"        if all(is_document(item) for item in input):\n            payload[\"input\"] = input\n        else:\n            for item in input:\n                if is_document(item):\n                    payload[\"input\"].append({\"text\": item})\n                elif is_image(item):\n                    try:\n                        pil_image = self._PILImage.fromarray(item)\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                    except Exception as e:\n                        raise ValueError(\n                            f\"Failed to convert image numpy array to base64 data URI: {e}\"\n                        ) from e\n                    payload[\"input\"].append({\"image\": base64_string})\n\n        if self.task is not None:\n            payload[\"task\"] = self.task\n        if self.late_chunking is not None:\n            payload[\"late_chunking\"] = self.late_chunking\n        if self.truncate is not None:\n            payload[\"truncate\"] = self.truncate\n        if self.dimensions is not None:\n            payload[\"dimensions\"] = self.dimensions\n        if self.embedding_type is not None:\n            payload[\"embedding_type\"] = self.embedding_type\n        if self.normalized is not None:\n            payload[\"normalized\"] = self.normalized\n\n        # overwrite parameteres when query payload is used","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/utils/embedding_functions/jina_embedding_function.py#L117-L153","documentation":"When a Jina EF input item is an image (numpy array, per is_image), _build_payload converts it via PIL.Image.fromarray → PNG-encode → base64. Any exception in that chain (almost always PIL.Image.fromarray raising on a non-image array) is wrapped in ValueError('Failed to convert image numpy array to base64 data URI: {e}'). fromarray requires a 2-D or 3-D array of uint8 (or a small set of other dtypes) with a sane channel axis; anything else (1-D vectors, object dtype, bool, wrong C/W ordering) fails.","triggerScenarios":"Passing a 1-D numpy array (e.g. a precomputed feature vector) as a document; an image array with dtype float64 or bool; an RGB array with a bogus shape like (3, H, W) or (H, W, 5); a zero-size array. Triggered on collection.add()/query() once payload building runs.","commonSituations":"Ingestion pipelines that feed raw numpy from cv2/PIL in unusual dtypes; documents mistakenly mixing embeddings (1-D floats) with images; images loaded with numpy.load from arbitrary .npy files.","solutions":["Normalize arrays before ingestion: arr = np.asarray(arr); assert arr.dtype == np.uint8 and arr.ndim in (2, 3)","Convert properly: PIL.Image.fromarray(np.uint8(arr)) or pass images opened via PIL and convert with np.asarray(img)","Fix channel layout: cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB) and ensure shape is (H, W, 3)","For non-image numeric arrays, don't send them as documents — precompute and use add_embeddings instead"],"exampleFix":"# before\ncollection.add(documents=[np.ones((128,), dtype=np.float32)], ids=[\"1\"])  # 1-D -> ValueError\n\n# after\nimg = np.asarray(pil_or_cv2_image)             # proper image source\nif img.ndim == 2:\n    img = np.stack([img] * 3, axis=-1)         # H,W -> H,W,3\nimg = np.ascontiguousarray(img, dtype=np.uint8)\ncollection.add(documents=[img], ids=[\"1\"])","handlingStrategy":"try-catch","validationCode":"import numpy as np\n\ndef to_image_array(arr: np.ndarray) -> np.ndarray:\n    arr = np.ascontiguousarray(arr)\n    if arr.ndim == 2:\n        arr = np.stack([arr] * 3, axis=-1)\n    if arr.dtype != np.uint8 or arr.ndim != 3 or arr.shape[2] not in (1, 3, 4):\n        raise ValueError(f\"not a valid image array: dtype={arr.dtype}, shape={arr.shape}\")\n    return arr\n\nimgs = [to_image_array(a) for a in image_arrays]\ncollection.add(documents=imgs, ids=ids)","typeGuard":"import numpy as np\n\ndef is_embeddable_image(x: object) -> bool:\n    \"\"\"True when PIL.Image.fromarray(x) will succeed for the Jina EF.\"\"\"\n    return (\n        isinstance(x, np.ndarray)\n        and x.ndim in (2, 3)\n        and x.dtype == np.uint8\n        and (x.ndim == 2 or x.shape[-1] in (3, 4))\n    )","tryCatchPattern":"try:\n    vectors = ef(image_arrays)\nexcept ValueError as e:\n    if \"Failed to convert image numpy array\" in str(e):\n        bad = [i for i, a in enumerate(image_arrays) if not is_embeddable_image(a)]\n        raise ValueError(f\"invalid image arrays at indices {bad}\") from e\n    raise","preventionTips":["Canonicalize images once at load time: RGB, uint8, (H, W, 3), C-contiguous","Never feed 1-D feature vectors as documents — embed them yourself and use add_embeddings","Unit-test your ingestion transform with PIL.Image.fromarray to guarantee the EF's conversion will succeed"],"tags":["python","numpy","pillow","image-processing","jina","multimodal"],"backgroundTag":"image-encoding-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}