{"record":{"id":"47efdec22f83813d","repo":"chroma-core/chroma","slug":"expected-ids-to-be-a-list-got-type-ids-name","errorCode":null,"errorMessage":"Expected IDs to be a list, got {type(ids).__name__} as IDs","messagePattern":"Expected IDs to be a list, got (.+?) as IDs","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/api/types.py","lineNumber":1017,"sourceCode":"    protocol_signature = signature(EmbeddingFunction.__call__).parameters.keys()\n\n    if not function_signature == protocol_signature:\n        raise ValueError(\n            f\"Expected EmbeddingFunction.__call__ to have the following signature: {protocol_signature}, got {function_signature}\\n\"\n            \"Please see https://docs.trychroma.com/guides/embeddings for details of the EmbeddingFunction interface.\\n\"\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\"\n        )\n\n\nclass DataLoader(Protocol[L]):\n    def __call__(self, uris: URIs) -> L:\n        ...\n\n\ndef validate_ids(ids: IDs) -> IDs:\n    \"\"\"Validates ids to ensure it is a list of strings\"\"\"\n    if not isinstance(ids, list):\n        raise ValueError(f\"Expected IDs to be a list, got {type(ids).__name__} as IDs\")\n    if len(ids) == 0:\n        raise ValueError(f\"Expected IDs to be a non-empty list, got {len(ids)} IDs\")\n    seen = set()\n    dups = set()\n    for id_ in ids:\n        if not isinstance(id_, str):\n            raise ValueError(f\"Expected ID to be a str, got {id_}\")\n        if id_ in seen:\n            dups.add(id_)\n        else:\n            seen.add(id_)\n    if dups:\n        n_dups = len(dups)\n        if n_dups < 10:\n            example_string = \", \".join(dups)\n            message = (\n                f\"Expected IDs to be unique, found duplicates of: {example_string}\"\n            )","sourceCodeStart":999,"sourceCodeEnd":1035,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/api/types.py#L999-L1035","documentation":"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'.","triggerScenarios":"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().","commonSituations":"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.","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"],"exampleFix":"# before\nids = np.array(['doc1', 'doc2'])\n\n# after\nids = np.array(['doc1', 'doc2']).tolist()","handlingStrategy":"type-guard","validationCode":"ids = list(ids) if not isinstance(ids, list) else ids\nids = [i.item() if hasattr(i, 'item') else i for i in ids]  # numpy scalars -> python\ncollection.add(ids=ids, documents=docs)","typeGuard":"def is_ids_list(ids) -> bool:\n    return isinstance(ids, list)","tryCatchPattern":"try:\n    validate_ids(ids)\nexcept ValueError as e:\n    if 'Expected IDs to be a list' in str(e):\n        ids = list(ids)\n        validate_ids(ids)\n    else:\n        raise","preventionTips":["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"],"tags":["chromadb","python","ids","validation","type-check"],"backgroundTag":"invalid-argument-type","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}