chroma-core/chroma · error · ValueError

Failed to convert image numpy array to base64 data URI: {e}

Error message

Failed to convert image numpy array to base64 data URI: {e}

What it means

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.

Source

Thrown at chromadb/utils/embedding_functions/jina_embedding_function.py:135

        if all(is_document(item) for item in input):
            payload["input"] = input
        else:
            for item in input:
                if is_document(item):
                    payload["input"].append({"text": item})
                elif is_image(item):
                    try:
                        pil_image = self._PILImage.fromarray(item)

                        buffer = io.BytesIO()
                        pil_image.save(buffer, format="PNG")
                        img_bytes = buffer.getvalue()

                        # Encode bytes to base64 string
                        base64_string = base64.b64encode(img_bytes).decode("utf-8")

                    except Exception as e:
                        raise ValueError(
                            f"Failed to convert image numpy array to base64 data URI: {e}"
                        ) from e
                    payload["input"].append({"image": base64_string})

        if self.task is not None:
            payload["task"] = self.task
        if self.late_chunking is not None:
            payload["late_chunking"] = self.late_chunking
        if self.truncate is not None:
            payload["truncate"] = self.truncate
        if self.dimensions is not None:
            payload["dimensions"] = self.dimensions
        if self.embedding_type is not None:
            payload["embedding_type"] = self.embedding_type
        if self.normalized is not None:
            payload["normalized"] = self.normalized

        # overwrite parameteres when query payload is used

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Normalize arrays before ingestion: arr = np.asarray(arr); assert arr.dtype == np.uint8 and arr.ndim in (2, 3)
  2. Convert properly: PIL.Image.fromarray(np.uint8(arr)) or pass images opened via PIL and convert with np.asarray(img)
  3. Fix channel layout: cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB) and ensure shape is (H, W, 3)
  4. For non-image numeric arrays, don't send them as documents — precompute and use add_embeddings instead

Example fix

# before
collection.add(documents=[np.ones((128,), dtype=np.float32)], ids=["1"])  # 1-D -> ValueError

# after
img = np.asarray(pil_or_cv2_image)             # proper image source
if img.ndim == 2:
    img = np.stack([img] * 3, axis=-1)         # H,W -> H,W,3
img = np.ascontiguousarray(img, dtype=np.uint8)
collection.add(documents=[img], ids=["1"])
Defensive patterns

Strategy: try-catch

Validate before calling

import numpy as np

def to_image_array(arr: np.ndarray) -> np.ndarray:
    arr = np.ascontiguousarray(arr)
    if arr.ndim == 2:
        arr = np.stack([arr] * 3, axis=-1)
    if arr.dtype != np.uint8 or arr.ndim != 3 or arr.shape[2] not in (1, 3, 4):
        raise ValueError(f"not a valid image array: dtype={arr.dtype}, shape={arr.shape}")
    return arr

imgs = [to_image_array(a) for a in image_arrays]
collection.add(documents=imgs, ids=ids)

Type guard

import numpy as np

def is_embeddable_image(x: object) -> bool:
    """True when PIL.Image.fromarray(x) will succeed for the Jina EF."""
    return (
        isinstance(x, np.ndarray)
        and x.ndim in (2, 3)
        and x.dtype == np.uint8
        and (x.ndim == 2 or x.shape[-1] in (3, 4))
    )

Try / catch

try:
    vectors = ef(image_arrays)
except ValueError as e:
    if "Failed to convert image numpy array" in str(e):
        bad = [i for i, a in enumerate(image_arrays) if not is_embeddable_image(a)]
        raise ValueError(f"invalid image arrays at indices {bad}") from e
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/e5ddcb747e7f611b. Report an issue: GitHub.