chroma-core/chroma · error · ValueError

Expected ID to be a str, got {id_}

Error message

Expected ID to be a str, got {id_}

What it means

Every id passed to add/upsert/update must be a Python str. validate_ids (chromadb/api/types.py:1024) iterates the list and raises on the first non-string element, echoing the offending value. This is the error you get for integer ids, uuid.UUID objects, or numpy str_ scalars - and also when a tuple/array was passed as a single value and auto-wrapped into one non-str element.

Source

Thrown at chromadb/api/types.py:1024

        )


class DataLoader(Protocol[L]):
    def __call__(self, uris: URIs) -> L:
        ...


def validate_ids(ids: IDs) -> IDs:
    """Validates ids to ensure it is a list of strings"""
    if not isinstance(ids, list):
        raise ValueError(f"Expected IDs to be a list, got {type(ids).__name__} as IDs")
    if len(ids) == 0:
        raise ValueError(f"Expected IDs to be a non-empty list, got {len(ids)} IDs")
    seen = set()
    dups = set()
    for id_ in ids:
        if not isinstance(id_, str):
            raise ValueError(f"Expected ID to be a str, got {id_}")
        if id_ in seen:
            dups.add(id_)
        else:
            seen.add(id_)
    if dups:
        n_dups = len(dups)
        if n_dups < 10:
            example_string = ", ".join(dups)
            message = (
                f"Expected IDs to be unique, found duplicates of: {example_string}"
            )
        else:
            examples = []
            for idx, dup in enumerate(dups):
                examples.append(dup)
                if idx == 10:
                    break
            example_string = (

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Stringify ids at the boundary: ids=[str(i) for i in ids]
  2. For pandas: df['id'].astype(str).tolist(); for UUIDs: [str(u) for u in uuids]
  3. Add a coercion guard in your ingestion wrapper so every write path normalizes once

Example fix

# before
collection.add(ids=[1, 2, 3], documents=docs)

# after
collection.add(ids=[str(i) for i in [1, 2, 3]], documents=docs)
Defensive patterns

Strategy: type-guard

Validate before calling

ids = [str(i) if not isinstance(i, str) else i for i in ids]
collection.add(ids=ids, documents=docs)

Type guard

def are_str_ids(ids) -> bool:
    return isinstance(ids, list) and all(isinstance(i, str) for i in ids)

Try / catch

try:
    collection.add(ids=ids, documents=docs)
except ValueError as e:
    if 'Expected ID to be a str' in str(e):
        collection.add(ids=[str(i) for i in ids], documents=docs)
    else:
        raise

Prevention

When it happens

Trigger: collection.add(ids=[1, 2, 3], ...) (integer ids); ids=[uuid.uuid4(), ...] (UUID objects); ids=df['id'].tolist() where the column dtype is int64; ids=('a','b') or np.array(['a','b']) which normalize wraps into a single non-str element.

Common situations: Auto-increment integer keys from SQL primary keys; pandas int64 id columns; UUID primary keys from ORM models; numpy str_ scalars which are not str instances.

Related errors


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