chroma-core/chroma · error · ValueError
Expected metadata to be a non-empty dict, got {len(metadata)
Error message
Expected metadata to be a non-empty dict, got {len(metadata)} metadata attributes What it means
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.
Source
Thrown at chromadb/api/types.py:1078
for item in value:
item_type = bool if isinstance(item, bool) else type(item)
if item_type is not first_type or item_type not in (str, int, float, bool):
raise ValueError(
f"Expected metadata list value for key '{key}' to contain only str, int, float, or bool "
f"and all elements must be the same type, got {value}"
)
def validate_metadata(metadata: Metadata) -> Metadata:
"""Validates metadata to ensure it is a dictionary of strings to strings, ints, floats, bools, SparseVectors, or lists thereof"""
if not isinstance(metadata, dict) and metadata is not None:
raise ValueError(
f"Expected metadata to be a dict or None, got {type(metadata).__name__} as metadata"
)
if metadata is None:
return metadata
if len(metadata) == 0:
raise ValueError(
f"Expected metadata to be a non-empty dict, got {len(metadata)} metadata attributes"
)
for key, value in metadata.items():
if key == META_KEY_CHROMA_DOCUMENT:
raise ValueError(
f"Expected metadata to not contain the reserved key {META_KEY_CHROMA_DOCUMENT}"
)
if not isinstance(key, str):
raise TypeError(
f"Expected metadata key to be a str, got {key} which is a {type(key).__name__}"
)
# Check if value is a SparseVector (validation happens in __post_init__)
if isinstance(value, SparseVector):
pass # Already validated in SparseVector.__post_init__
elif isinstance(value, list):
_validate_metadata_list_value(key, value)
# isinstance(True, int) evaluates to True, so we need to check for bools separately
elif not isinstance(value, bool) and not isinstance(View on GitHub (pinned to aecdd12c8a)
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
Example fix
# before
collection.add(ids=ids, metadatas=[row_to_meta(r) for r in rows]) # some are {}
# after
collection.add(ids=ids, metadatas=[row_to_meta(r) or None for r in rows]) Defensive patterns
Strategy: validation
Validate before calling
metadatas = [m if m else None for m in metadatas] collection.add(ids=ids, metadatas=metadatas)
Type guard
def has_no_empty_metadata_dicts(metadatas) -> bool:
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) Try / catch
try:
collection.add(ids=ids, metadatas=metas)
except ValueError as e:
if 'non-empty dict' in str(e):
collection.add(ids=ids, metadatas=[m or None for m in metas])
else:
raise Prevention
- Default missing metadata to None, not {}
- Build metadata dicts conditionally so empty ones never exist
- Omit the metadatas argument when no record has metadata
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Expected metadata to be a non-empty dict, got {metadata}
- Expected metadata list value for key '{key}' to be non-empty
- Expected metadata list value for key '{key}' to contain only
- Expected metadata to be a dict or None, got {type(metadata).
- Expected metadata to not contain the reserved key {META_KEY_
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/56a3cf9124046f11.
Report an issue: GitHub.