chroma-core/chroma · error · ValueError
Expected #type='sparse_vector', got {d.get(TYPE_KEY)}
Error message
Expected #type='sparse_vector', got {d.get(TYPE_KEY)} What it means
SparseVector.from_dict (chromadb/base_types.py) is the strict deserializer for the tagged wire format. It requires d['#type'] == 'sparse_vector' (TYPE_KEY / SPARSE_VECTOR_TYPE_VALUE) and raises ValueError showing the value it actually found (commonly None). Plain dicts like {'indices': [...], 'values': [...]} are rejected because the tag is what distinguishes a sparse vector from arbitrary metadata.
Source
Thrown at chromadb/base_types.py:109
"""
result = {
TYPE_KEY: SPARSE_VECTOR_TYPE_VALUE,
"indices": self.indices,
"values": self.values,
}
if self.labels is not None:
result["tokens"] = self.labels # Wire format uses 'tokens'
return result
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> "SparseVector":
"""Deserialize from transport format (strict - requires #type field).
Note: Reads from 'tokens' key in the wire format for compatibility
with the protobuf schema, mapping it to the 'labels' attribute.
"""
if d.get(TYPE_KEY) != SPARSE_VECTOR_TYPE_VALUE:
raise ValueError(
f"Expected {TYPE_KEY}='{SPARSE_VECTOR_TYPE_VALUE}', got {d.get(TYPE_KEY)}"
)
return cls(
indices=d["indices"],
values=d["values"],
labels=d.get("tokens"), # Wire format uses 'tokens'
)
MetadataListValue = List[Union[str, int, float, bool]]
Metadata = Mapping[
str, Optional[Union[str, int, float, bool, SparseVector, MetadataListValue]]
]
UpdateMetadata = Mapping[
str, Union[int, float, str, bool, SparseVector, MetadataListValue, None]
]
PyVector = Union[Sequence[float], Sequence[int]]
Vector = NDArray[Union[np.int32, np.float32]] # TODO: Specify that the vector is 1DView on GitHub (pinned to aecdd12c8a)
Solutions
- Add the tag before deserializing: d['#type'] = 'sparse_vector' (labels go under the 'tokens' key).
- Produce wire dicts with SparseVector.to_dict() so '#type' is always present on the write side.
- For untrusted input, check d.get('#type') first, or bypass from_dict and construct directly: SparseVector(indices=d['indices'], values=d['values'], labels=d.get('tokens')).
Example fix
// before
d = {'indices': [1, 5], 'values': [0.2, 0.4]}
sv = SparseVector.from_dict(d) # ValueError: got None
// after
d = {'#type': 'sparse_vector', 'indices': [1, 5], 'values': [0.2, 0.4]}
sv = SparseVector.from_dict(d) Defensive patterns
Strategy: validation
Validate before calling
TYPE_KEY, SPARSE_VECTOR_TYPE_VALUE = '#type', 'sparse_vector'
if d.get(TYPE_KEY) != SPARSE_VECTOR_TYPE_VALUE:
# only add the tag if you KNOW the dict is a sparse vector payload
d = {**d, TYPE_KEY: SPARSE_VECTOR_TYPE_VALUE}
sv = SparseVector.from_dict(d) # labels are read from the 'tokens' key Type guard
def is_sparse_vector_dict(d: object) -> bool:
return (
isinstance(d, dict)
and d.get('#type') == 'sparse_vector'
and isinstance(d.get('indices'), list)
and isinstance(d.get('values'), list)
) Try / catch
try:
sv = SparseVector.from_dict(d)
except ValueError as e:
raise ValueError(f'payload is not a tagged sparse vector: {e}') from e Prevention
- Always write sparse vectors with SparseVector.to_dict() so '#type' is present by construction.
- Keep '#'-prefixed keys intact through any serialization middleware - do not strip unknown keys.
- Version your stored payloads and re-validate with is_sparse_vector_dict before deserializing.
When it happens
Trigger: Calling SparseVector.from_dict() on a hand-built dict that lacks the '#type' key; round-tripping a to_dict() result through code that strips unknown keys (e.g. a strict schema or a different library version); passing another type's tagged dict.
Common situations: Reading sparse vectors back from user-managed storage (JSON files, other DBs) where the producer never wrote '#type'; version mismatches where an older Chroma wrote dicts without the tag; middleware that filters keys starting with '#'.
Related errors
- Expected dict with {TYPE_KEY}='{SPARSE_VECTOR_TYPE_VALUE}',
- Sparse vector index must be created on a specific key. Pleas
- Deleting sparse vector index is not currently supported.
- Invalid parameter name: {parameter.name}
- Invalid configuration type: {parameter.value}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/954a9c3089548f7c.
Report an issue: GitHub.