chroma-core/chroma · error · ValueError
Expected IDs to be a list, got {type(ids).__name__} as IDs
Error message
Expected IDs to be a list, got {type(ids).__name__} as IDs What it means
validate_ids (chromadb/api/types.py:1011) requires the ids argument to be a Python list of strings. Through the public collection API a single non-list value is auto-wrapped into a one-element list by maybe_cast_one_to_many (types.py:140), so in practice this message surfaces when the validation helper is used directly - e.g. ids passed as a tuple, numpy array, set or generator to validate_ids. Note that via collection.add() a tuple/array is wrapped as a single element and instead fails with 'Expected ID to be a str'.
Source
Thrown at chromadb/api/types.py:1017
protocol_signature = signature(EmbeddingFunction.__call__).parameters.keys()
if not function_signature == protocol_signature:
raise ValueError(
f"Expected EmbeddingFunction.__call__ to have the following signature: {protocol_signature}, got {function_signature}\n"
"Please see https://docs.trychroma.com/guides/embeddings for details of the EmbeddingFunction interface.\n"
"Please note the recent change to the EmbeddingFunction interface: https://docs.trychroma.com/deployment/migration#migration-to-0.4.16---november-7,-2023 \n"
)
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}"
)View on GitHub (pinned to aecdd12c8a)
Solutions
- Convert to a plain list at the boundary: ids = list(ids), and use np.asarray(ids).tolist() for arrays
- Through the public API, pass either a list of strings or a single bare string (it gets wrapped)
- Annotate the ingestion boundary as List[str] and normalize early
Example fix
# before ids = np.array(['doc1', 'doc2']) # after ids = np.array(['doc1', 'doc2']).tolist()
Defensive patterns
Strategy: type-guard
Validate before calling
ids = list(ids) if not isinstance(ids, list) else ids ids = [i.item() if hasattr(i, 'item') else i for i in ids] # numpy scalars -> python collection.add(ids=ids, documents=docs)
Type guard
def is_ids_list(ids) -> bool:
return isinstance(ids, list) Try / catch
try:
validate_ids(ids)
except ValueError as e:
if 'Expected IDs to be a list' in str(e):
ids = list(ids)
validate_ids(ids)
else:
raise Prevention
- Always .tolist() numpy arrays and list() tuples at the ingestion boundary
- Type-annotate ingestion functions as List[str]
- Normalize ids in one shared helper used by every write path
When it happens
Trigger: Calling chromadb.api.types.validate_ids(np.array(['a','b'])) or validate_ids({'a','b'}) or validate_ids(i for i in ids); test suites and ingestion frameworks that call the validator directly; ids converted from numpy/pandas without .tolist().
Common situations: Direct use of Chroma's exported validators; converting ids from pandas Series or numpy arrays; ids arriving as tuples from database drivers or JSON decoders.
Related errors
- Expected IDs to be a non-empty list, got {len(ids)} IDs
- Expected ID to be a str, got {id_}
- Expected metadata to be a dict or None, got {type(metadata).
- Expected metadata to be a dict or None, got {type(metadata)}
- Expected 'ids' to be an array, but got ${typeof ids}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/47efdec22f83813d.
Report an issue: GitHub.