chroma-core/chroma · error · InvalidDimensionException

InvalidDimension

InvalidDimension

Error message

Embedding dimension {dim} does not match collection dimensionality {collection['dimension']}

What it means

A Chroma collection is single-dimension: the first write sets collection['dimension'], and SegmentAPI._validate_dimension (reached via _validate_embedding_record_set on add/upsert) compares every subsequent embedding against it. On a mismatch it raises InvalidDimensionException (error code InvalidDimension) naming both the incoming dim and the collection's. You cannot mix embedding models of different sizes in one collection.

Solutions

  1. Recreate the collection after changing the embedding model: client.delete_collection(name) then get_or_create_collection with the new embedding_function
  2. Route every write through one embedding function so dimensions stay consistent
  3. Pre-check len(embedding) == collection.dimension (dimension is set after the first write) before add/upsert

Example fix

// before
coll.add(ids=['1'], embeddings=[[0.1] * 384])  # collection dim is 1536 -> InvalidDimensionException

// after
if getattr(coll, 'dimension', None) not in (None, 384):
    client.delete_collection(coll.name)
    coll = client.get_or_create_collection('docs', embedding_function=ef386)
coll.add(ids=['1'], embeddings=[[0.1] * 384])
Defensive patterns

Strategy: validation

Validate before calling

def check_dimensions(coll, embeddings) -> None:
    dim = getattr(coll, 'dimension', None)
    if dim is None:
        return  # first write sets the dimension
    bad = [i for i, e in enumerate(embeddings) if len(e) != dim]
    if bad:
        raise ValueError(f'{len(bad)} embeddings have dimension != {dim} (e.g. index {bad[0]})')

check_dimensions(coll, embeddings)
coll.add(ids=ids, embeddings=embeddings)

Type guard

def embeddings_match_dimension(coll, embeddings) -> bool:
    dim = getattr(coll, 'dimension', None)
    return dim is None or all(len(e) == dim for e in embeddings)

Try / catch

from chromadb.errors import InvalidDimensionException

try:
    coll.add(ids=ids, embeddings=embeddings)
except InvalidDimensionException:
    raise RuntimeError(
        f'collection {coll.name} has dimension {coll.dimension}; '
        f'recreate it before switching embedding models') from None

Prevention

When it happens

Trigger: coll.add(ids=..., embeddings=[[...]]) or upsert where the collection already has dimension N and the supplied vectors have a different length — e.g. 384-dim MiniLM vectors written into a 1536-dim OpenAI collection, or hand-built vectors of the wrong length.

Common situations: Switching embedding models (or the default embedding function) without recreating the collection; mixing default all-MiniLM-L6-v2 (384) with a custom embedding function; reusing an old persist directory with a new model; inconsistent vector lengths from buggy preprocessing.

Related errors


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

Appendix: source

Thrown at chromadb/api/segment.py:1153

            if record["embedding"] is not None:
                self._validate_dimension(
                    collection, len(record["embedding"]), update=True
                )

    # This method is intentionally left untraced because otherwise it can emit thousands of spans for requests containing many embeddings.
    def _validate_dimension(
        self, collection: t.Collection, dim: int, update: bool
    ) -> None:
        """Validate that a collection supports records of the given dimension. If update
        is true, update the collection if the collection doesn't already have a
        dimension."""
        if collection["dimension"] is None:
            if update:
                id = collection.id
                self._sysdb.update_collection(id=id, dimension=dim)
                collection["dimension"] = dim
        elif collection["dimension"] != dim:
            raise InvalidDimensionException(
                f"Embedding dimension {dim} does not match collection dimensionality {collection['dimension']}"
            )
        else:
            return  # all is well

    @trace_method("SegmentAPI._get_collection", OpenTelemetryGranularity.ALL)
    def _get_collection(self, collection_id: UUID) -> t.Collection:
        collections = self._sysdb.get_collections(id=collection_id)
        if not collections or len(collections) == 0:
            raise NotFoundError(f"Collection {collection_id} does not exist.")
        return collections[0]

    @trace_method("SegmentAPI._scan", OpenTelemetryGranularity.OPERATION)
    def _scan(self, collection_id: UUID) -> Scan:
        collection_and_segments = self._sysdb.get_collection_with_segments(
            collection_id
        )
        # For now collection should have exactly one segment per scope:

View on GitHub (pinned to aecdd12c8a)