{"record":{"id":"e60d166c306ebdc8","repo":"chroma-core/chroma","slug":"expected-embeddings-to-be-non-empty-list-or-numpy","errorCode":null,"errorMessage":"Expected Embeddings to be non-empty list or numpy array, got {target}","messagePattern":"Expected Embeddings to be non-empty list or numpy array, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/api/types.py","lineNumber":230,"sourceCode":"    for b64_string in b64_strings:\n        if b64_string is None:\n            embeddings.append(None)  # type: ignore\n        else:\n            packed_data = pybase64.b64decode(b64_string)\n            vector_length = len(packed_data) // 4\n            embedding_tuple = _get_struct(vector_length).unpack(packed_data)\n            embeddings.append(list(embedding_tuple))\n    return embeddings\n\n\ndef normalize_embeddings(\n    target: Optional[Union[OneOrMany[Embedding], OneOrMany[PyEmbedding]]],\n) -> Optional[Embeddings]:\n    if target is None:\n        return None\n\n    if len(target) == 0:\n        raise ValueError(\n            f\"Expected Embeddings to be non-empty list or numpy array, got {target}\"\n        )\n\n    if isinstance(target, np.ndarray):\n        if target.ndim == 1:\n            return [target]\n        elif target.ndim == 2:\n            return [row for row in target]\n    elif isinstance(target, list):\n        # One PyEmbedding\n        if isinstance(target[0], (int, float)) and not isinstance(target[0], bool):\n            return [np.array(target, dtype=np.float32)]\n        elif isinstance(target[0], np.ndarray):\n            return cast(Embeddings, target)\n        elif isinstance(target[0], list):\n            if isinstance(target[0][0], (int, float)) and not isinstance(\n                target[0][0], bool\n            ):","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/api/types.py#L212-L248","documentation":"normalize_embeddings, which runs on the embeddings argument of add/upsert/query, rejects empty input: when len(target) == 0 it raises ValueError('Expected Embeddings to be non-empty list or numpy array'). If embeddings are provided at all, they must contain at least one vector — there is no meaningful empty write or empty query.","triggerScenarios":"coll.add(ids=[], embeddings=[]), coll.query(query_embeddings=[]), or passing np.array([]) — any zero-length embeddings list or array.","commonSituations":"Ingestion loops that call add() on an empty batch instead of skipping it; an embedding function returning [] for empty text; batch pipelines handing off empty DataFrames.","solutions":["Skip the call when the batch is empty: if not embeddings: return","Fix upstream producers so empty batches never reach the client","Pass None (letting the collection's embedding function compute) rather than an empty list when you have documents but no vectors"],"exampleFix":"// before\ncoll.add(ids=ids, embeddings=embs)  # embs == [] -> ValueError\n\n// after\nif embs:\n    coll.add(ids=ids, embeddings=embs)","handlingStrategy":"validation","validationCode":"def add_batch(coll, ids, embeddings):\n    if not embeddings:\n        return  # nothing to write — skip instead of erroring\n    coll.add(ids=ids, embeddings=embeddings)\n\ndef query_safe(coll, query_embeddings):\n    if not query_embeddings:\n        return None\n    return coll.query(query_embeddings=query_embeddings)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Skip empty batches in ingestion loops instead of calling add with []","Make embedding functions raise a clear error on empty input rather than returning []","Assert non-empty inputs at batch boundaries in tests"],"tags":["chroma","embeddings","empty-input","validation","add"],"backgroundTag":"empty-input-list","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}