chroma-core/chroma · error · ValueError
Expected metadata value to be a str, int, float, bool, Spars
Error message
Expected metadata value to be a str, int, float, bool, SparseVector, list, or None, got {value} What it means
Per-record metadata values on update must be str, int, float, bool, None, a SparseVector, or a homogeneous list of scalars - the same flat rule as the insert path, checked by validate_update_metadata (chromadb/api/types.py:1127, reached from collection.update via chromadb/segment.py:407). None is allowed and means 'delete this key'. Nested dicts, datetime, Decimal, tuples, sets and numpy scalars raise this error.
Source
Thrown at chromadb/api/types.py:1127
f"Expected metadata to be a dict or None, got {type(metadata)}"
)
if metadata is None:
return metadata
if len(metadata) == 0:
raise ValueError(f"Expected metadata to be a non-empty dict, got {metadata}")
for key, value in metadata.items():
if not isinstance(key, str):
raise ValueError(f"Expected metadata key to be a str, got {key}")
# 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(
value, (str, int, float, type(None))
):
raise ValueError(
f"Expected metadata value to be a str, int, float, bool, SparseVector, list, or None, got {value}"
)
return metadata
def serialize_metadata(metadata: Optional[Metadata]) -> Optional[Dict[str, Any]]:
"""Serialize metadata for transport, converting SparseVector dataclass instances to dicts.
Args:
metadata: Metadata dictionary that may contain SparseVector instances
Returns:
Metadata dictionary with SparseVector instances converted to transport format
"""
if metadata is None:
return None
result: Dict[str, Any] = {}View on GitHub (pinned to aecdd12c8a)
Solutions
- Convert datetimes to isoformat strings or epoch floats, Decimals to float(), numpy scalars with .item()
- Use None (not {} or []) to clear a metadata key on update
- Reuse the same normalize_metadata() helper for add and update so both paths enforce identical rules
Example fix
# before
collection.update(ids=ids, metadatas=[{'ts': now, 'p': prob}]) # datetime, np.float32
# after
collection.update(ids=ids, metadatas=[{'ts': now.isoformat(), 'p': float(prob)}]) Defensive patterns
Strategy: type-guard
Validate before calling
from datetime import datetime, date
def normalize_update_value(v):
if isinstance(v, (datetime, date)):
return v.isoformat()
if hasattr(v, 'item'):
return v.item()
if isinstance(v, tuple):
return list(v)
return v
metas = [{k: normalize_update_value(v) for k, v in m.items()} for m in metas]
collection.update(ids=ids, metadatas=metas) Type guard
def is_valid_update_value(v) -> bool:
if v is None or isinstance(v, (str, int, float, bool)):
return True
if isinstance(v, list) and v:
ts = {bool if isinstance(x, bool) else type(x) for x in v}
return len(ts) == 1 and next(iter(ts)) in (str, int, float, bool)
return False Try / catch
try:
collection.update(ids=ids, metadatas=metas)
except ValueError as e:
if 'Expected metadata value to be a str, int, float, bool, SparseVector, list, or None' in str(e):
metas = [{k: normalize_update_value(v) for k, v in m.items()} for m in metas]
collection.update(ids=ids, metadatas=metas)
else:
raise Prevention
- Share one normalize_metadata() between add and update paths
- Use None to delete a key on update, not {} or []
- Convert datetime/Decimal/numpy values before they reach Chroma
When it happens
Trigger: collection.update(ids=..., metadatas=[{'ts': datetime.now()}]); {'conf': np.float32(0.9)}; {'obj': {'a': 1}}; {'tags': ('a','b')} (tuple is not a list); writing ORM or pandas values back without normalization.
Common situations: Updating ORM/pandas objects with datetime or Decimal columns; updating probabilities held as numpy scalars; assuming tuples count as lists; reusing insert-path payloads that were never normalized.
Related errors
- Expected metadata list value for key '{key}' to contain only
- Expected metadata value to be a str, int, float, bool, Spars
- Expected metadata to be a dict or None, got {type(metadata)}
- Expected metadata to be a non-empty dict, got {metadata}
- Expected metadata key to be a str, got {key}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/2b75085fdc52f4c4.
Report an issue: GitHub.