{"record":{"id":"56a3cf9124046f11","repo":"chroma-core/chroma","slug":"expected-metadata-to-be-a-non-empty-dict-got-len","errorCode":null,"errorMessage":"Expected metadata to be a non-empty dict, got {len(metadata)} metadata attributes","messagePattern":"Expected metadata to be a non-empty dict, got (.+?) metadata attributes","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/api/types.py","lineNumber":1078,"sourceCode":"    for item in value:\n        item_type = bool if isinstance(item, bool) else type(item)\n        if item_type is not first_type or item_type not in (str, int, float, bool):\n            raise ValueError(\n                f\"Expected metadata list value for key '{key}' to contain only str, int, float, or bool \"\n                f\"and all elements must be the same type, got {value}\"\n            )\n\n\ndef validate_metadata(metadata: Metadata) -> Metadata:\n    \"\"\"Validates metadata to ensure it is a dictionary of strings to strings, ints, floats, bools, SparseVectors, or lists thereof\"\"\"\n    if not isinstance(metadata, dict) and metadata is not None:\n        raise ValueError(\n            f\"Expected metadata to be a dict or None, got {type(metadata).__name__} as metadata\"\n        )\n    if metadata is None:\n        return metadata\n    if len(metadata) == 0:\n        raise ValueError(\n            f\"Expected metadata to be a non-empty dict, got {len(metadata)} metadata attributes\"\n        )\n    for key, value in metadata.items():\n        if key == META_KEY_CHROMA_DOCUMENT:\n            raise ValueError(\n                f\"Expected metadata to not contain the reserved key {META_KEY_CHROMA_DOCUMENT}\"\n            )\n        if not isinstance(key, str):\n            raise TypeError(\n                f\"Expected metadata key to be a str, got {key} which is a {type(key).__name__}\"\n            )\n        # Check if value is a SparseVector (validation happens in __post_init__)\n        if isinstance(value, SparseVector):\n            pass  # Already validated in SparseVector.__post_init__\n        elif isinstance(value, list):\n            _validate_metadata_list_value(key, value)\n        # isinstance(True, int) evaluates to True, so we need to check for bools separately\n        elif not isinstance(value, bool) and not isinstance(","sourceCodeStart":1060,"sourceCodeEnd":1096,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/api/types.py#L1060-L1096","documentation":"In the insert path (add/upsert and collection.modify) an empty dict {} is not valid metadata - Chroma treats it as an invalid input rather than 'no metadata'. validate_metadata raises as soon as one record's metadata is {}. Use None per record to express 'this record has no metadata'; omit the argument entirely when no record has any.","triggerScenarios":"collection.add(ids=..., metadatas=[{}, {'k': 1}]); a dataframe metadata column where some rows produce row.to_dict() == {}; collection.modify(metadata={}) attempting to send empty collection metadata.","commonSituations":"row.to_dict() on rows without attributes; default {} instead of None in ingestion code; attempting to 'clear' metadata by passing an empty dict instead of omitting the key.","solutions":["Convert empty dicts to None: metadatas=[m if m else None for m in metadatas]","Omit the metadatas argument when no record carries metadata","Build metadata dicts conditionally so empty ones are never constructed"],"exampleFix":"# before\ncollection.add(ids=ids, metadatas=[row_to_meta(r) for r in rows])  # some are {}\n\n# after\ncollection.add(ids=ids, metadatas=[row_to_meta(r) or None for r in rows])","handlingStrategy":"validation","validationCode":"metadatas = [m if m else None for m in metadatas]\ncollection.add(ids=ids, metadatas=metadatas)","typeGuard":"def has_no_empty_metadata_dicts(metadatas) -> bool:\n    return all(m is None or len(m) > 0 for m in metadatas if m is not None) and all(m is None or isinstance(m, dict) for m in metadatas)","tryCatchPattern":"try:\n    collection.add(ids=ids, metadatas=metas)\nexcept ValueError as e:\n    if 'non-empty dict' in str(e):\n        collection.add(ids=ids, metadatas=[m or None for m in metas])\n    else:\n        raise","preventionTips":["Default missing metadata to None, not {}","Build metadata dicts conditionally so empty ones never exist","Omit the metadatas argument when no record has metadata"],"tags":["chromadb","python","metadata","empty-dict","validation"],"backgroundTag":"empty-metadata-dict","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}