chroma-core/chroma · error · ValueError

Expected embeddings to be a list of floats or ints, a list o

Error message

Expected embeddings to be a list of floats or ints, a list of lists, a numpy array, or a list of numpy arrays, got {target}

What it means

normalize_embeddings accepts exactly four shapes: a 1-D or 2-D numpy array, a flat list of ints/floats (a single embedding), a list of numpy arrays, or a list of lists of ints/floats. Everything else — strings, bools, extra nesting, tensors, arbitrary objects — falls through every branch to ValueError('Expected embeddings to be a list of floats or ints, a list of lists, a numpy array, or a list of numpy arrays').

Source

Thrown at chromadb/api/types.py:251

    if isinstance(target, np.ndarray):
        if target.ndim == 1:
            return [target]
        elif target.ndim == 2:
            return [row for row in target]
    elif isinstance(target, list):
        # One PyEmbedding
        if isinstance(target[0], (int, float)) and not isinstance(target[0], bool):
            return [np.array(target, dtype=np.float32)]
        elif isinstance(target[0], np.ndarray):
            return cast(Embeddings, target)
        elif isinstance(target[0], list):
            if isinstance(target[0][0], (int, float)) and not isinstance(
                target[0][0], bool
            ):
                return [np.array(row, dtype=np.float32) for row in target]

    raise ValueError(
        f"Expected embeddings to be a list of floats or ints, a list of lists, a numpy array, or a list of numpy arrays, got {target}"
    )


# Metadatas
Metadatas = List[Metadata]

CollectionMetadata = Dict[str, Any]
UpdateCollectionMetadata = UpdateMetadata


def normalize_metadata(metadata: Optional[Metadata]) -> Optional[Metadata]:
    """
    Normalize metadata by converting dict-format sparse vectors to SparseVector instances.

    Accepts:
    - SparseVector instances (pass through)
    - Dict with #type='sparse_vector' (convert to SparseVector)

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Convert before the call: np.asarray(embeddings, dtype=np.float32) shaped 1-D or 2-D, or [[float(x) for x in v] for v in vecs]
  2. For tensors: tensor.detach().cpu().numpy() (or .tolist()) before passing
  3. Validate the first element's type (int/float excluding bool, np.ndarray, or list of numbers) before sending

Example fix

// before
coll.add(ids=['1'], embeddings=[['0.1', '0.2']])  # strings -> ValueError

// after
import numpy as np
emb = np.asarray([[0.1, 0.2]], dtype=np.float32)
coll.add(ids=['1'], embeddings=emb)
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np

def to_embeddings(value):
    arr = np.asarray(value, dtype=np.float32)
    if arr.ndim == 1:
        arr = arr.reshape(1, -1)
    if arr.ndim != 2 or arr.shape[0] == 0:
        raise ValueError(f'cannot interpret {type(value)} as embeddings')
    return arr

coll.add(ids=ids, embeddings=to_embeddings(raw))

Type guard

import numpy as np

def is_normalizable_embeddings(v) -> bool:
    if isinstance(v, np.ndarray):
        return v.ndim in (1, 2) and v.size > 0
    if isinstance(v, list) and len(v) > 0:
        first = v[0]
        if isinstance(first, (int, float)) and not isinstance(first, bool):
            return True
        if isinstance(first, np.ndarray):
            return True
        if (isinstance(first, list) and first
                and isinstance(first[0], (int, float))
                and not isinstance(first[0], bool)):
            return True
    return False

Try / catch

try:
    coll.add(ids=ids, embeddings=raw)
except ValueError as e:
    if 'Expected embeddings' not in str(e):
        raise
    coll.add(ids=ids, embeddings=np.asarray(raw, dtype=np.float32))

Prevention

When it happens

Trigger: coll.add(embeddings=[['0.1','0.2']]) (numeric strings), embeddings=[True, False] (bools are explicitly rejected), embeddings=[[[0.1],[0.2]]] (three levels of nesting), or passing a torch.Tensor / pandas object directly.

Common situations: Embeddings loaded from JSON/CSV where numbers deserialize as strings; passing tensors without .tolist()/numpy(); bool masks mistaken for float vectors; wrapping a single vector in one bracket pair too many.

Related errors


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