chroma-core/chroma · error · ValueError
Expected where document operand value for operator {operator
Error message
Expected where document operand value for operator {operator} to be a non-empty str What it means
validate_where_document requires the operand of $contains/$not_contains/$regex/$not_regex to be a NON-EMPTY string. An empty string ("") is rejected because matching an empty substring/pattern is meaningless in Chroma's document filter engine.
Source
Thrown at chromadb/api/types.py:1330
)
if operator == "$and" or operator == "$or":
if not isinstance(operand, list):
raise ValueError(
f"Expected document value for $and or $or to be a list of where document expressions, got {operand}"
)
if len(operand) <= 1:
raise ValueError(
f"Expected document value for $and or $or to be a list with at least two where document expressions, got {operand}"
)
for where_document_expression in operand:
validate_where_document(where_document_expression)
# Value is $contains/$not_contains/$regex/$not_regex operator
elif not isinstance(operand, str):
raise ValueError(
f"Expected where document operand value for operator {operator} to be a str, got {operand}"
)
elif len(operand) == 0:
raise ValueError(
f"Expected where document operand value for operator {operator} to be a non-empty str"
)
def validate_include(include: Include, dissalowed: Optional[Include] = None) -> None:
"""Validates include to ensure it is a list of strings. Since get does not allow distances, allow_distances is used
to control if distances is allowed"""
if not isinstance(include, list):
raise ValueError(f"Expected include to be a list, got {include}")
for item in include:
if not isinstance(item, str):
raise ValueError(f"Expected include item to be a str, got {item}")
# Get the valid items from the Literal type inside the List
valid_items = get_args(get_args(Include)[0])
if item not in valid_items:
raise ValueError(View on GitHub (pinned to aecdd12c8a)
Solutions
- Skip the where_document filter entirely when the value is empty instead of sending {"$contains": ""}
- Default optional filter variables to None and build the filter only if the value is truthy
- For search-as-you-type, guard the request with: if not query.strip(): return []
Example fix
# before
results = collection.query(query_texts=[q], where_document={"$contains": search_term}) # search_term == ""
# after
if search_term:
results = collection.query(query_texts=[q], where_document={"$contains": search_term})
else:
results = collection.query(query_texts=[q], n_results=5) Defensive patterns
Strategy: validation
Validate before calling
def optional_contains(term: str | None) -> dict | None:
"""Return a $contains filter only for non-empty terms."""
if term is None or not term.strip():
return None
return {"$contains": term}
wd = optional_contains(user_query)
kwargs = {"where_document": wd} if wd else {}
res = collection.query(query_texts=[q], n_results=5, **kwargs) Type guard
def is_non_empty_str_operand(wd: dict) -> bool:
if len(wd) != 1:
return False
op, operand = next(iter(wd.items()))
return op in ("$contains", "$not_contains", "$regex", "$not_regex") and isinstance(operand, str) and len(operand) > 0 Try / catch
try:
res = collection.query(query_texts=[q], where_document={"$contains": term}, n_results=5)
except ValueError as e:
if "non-empty str" in str(e):
res = collection.query(query_texts=[q], n_results=5) # retry without the filter
else:
raise Prevention
- Default optional filter inputs to None, never ""
- In search-as-you-type UIs, short-circuit empty input before issuing the query
- Strip and check truthiness of template variables used inside $contains
When it happens
Trigger: collection.get(where_document={"$contains": ""}) — typically the string comes from an f-string or variable that is empty at runtime, e.g. {"$contains": user_query} when user_query == "", or a config/env value that was never set.
Common situations: Search-as-you-type UIs issuing a query on every keystroke, including the empty input; optional filter parameters defaulting to "" instead of None; stripping whitespace from user input leaving "".
Related errors
- Expected document value for $and or $or to be a list with at
- Expected where document operand value for operator {operator
- Expected include to be a list, got {include}
- Expected include item to be a str, got {item}
- Expected embeddings to be a list, got {type(embeddings).__na
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/af5ab6c028246641.
Report an issue: GitHub.