mem0ai/mem0 · error · ValueError
AND operator requires a list of conditions
Error message
AND operator requires a list of conditions
What it means
Raised inside _process_metadata_filters when the top-level 'AND' key in a filters dict has a value that is not a list. The AND construct combines multiple condition dicts and its contract is filters={'AND': [{'a':{'gte':1}}, {'b':{'eq':2}}]} — passing a single dict, a tuple, a string, or a nested dict of dicts triggers this ValueError before any vector-store translation.
Source
Thrown at mem0/memory/main.py:1571
if operator in operator_map:
result.setdefault(key, {})[operator_map[operator]] = value
else:
raise ValueError(f"Unsupported metadata filter operator: {operator}")
return result
def merge_filters(target: Dict[str, Any], source: Dict[str, Any]) -> None:
"""Merge source into target, deep-merging nested operator dicts for the same key."""
for key, value in source.items():
if key in target and isinstance(target[key], dict) and isinstance(value, dict):
target[key].update(value)
else:
target[key] = value
for key, value in metadata_filters.items():
if key == "AND":
# Logical AND: combine multiple conditions
if not isinstance(value, list):
raise ValueError("AND operator requires a list of conditions")
for condition in value:
for sub_key, sub_value in condition.items():
merge_filters(processed_filters, process_condition(sub_key, sub_value))
elif key == "OR":
# Logical OR: Pass through to vector store for implementation-specific handling
if not isinstance(value, list) or not value:
raise ValueError("OR operator requires a non-empty list of conditions")
# Store OR conditions in a way that vector stores can interpret
processed_filters["$or"] = []
for condition in value:
or_condition = {}
for sub_key, sub_value in condition.items():
merge_filters(or_condition, process_condition(sub_key, sub_value))
processed_filters["$or"].append(or_condition)
elif key == "NOT":
# Logical NOT: Pass through to vector store for implementation-specific handling
if not isinstance(value, list) or not value:
raise ValueError("NOT operator requires a non-empty list of conditions")View on GitHub (pinned to 001c235229)
Solutions
- Wrap conditions in a list: {'AND': [cond1, cond2]} with each condition its own dict.
- If there is only one condition, skip AND entirely: just use {'a': {'gte': 1}}.
- When building programmatically, accumulate a list: conds.append({...}) then filters={'AND': conds} only if len(conds) > 1.
- Validate isinstance(value, list) for logical keys before the call.
Example fix
# before
filters = {"AND": {"user_id": "u1", "tag": "work"}}
# after
filters = {"AND": [{"user_id": "u1"}, {"tag": "work"}]} Defensive patterns
Strategy: validation
Validate before calling
if "AND" in filters and not isinstance(filters["AND"], list):
filters["AND"] = [filters["AND"]] # or raise your own error Type guard
def is_valid_logical_filter(key: str, value) -> bool:
if key == "AND":
return isinstance(value, list)
return isinstance(value, list) and len(value) > 0 # OR / NOT Prevention
- AND takes a list of condition dicts: {'AND': [c1, c2]}.
- Single condition? Skip AND and use the condition directly at top level.
- In builders, accumulate a list and only add the AND key when len > 1.
When it happens
Trigger: filters={'AND': {'user_id':'u1','tag':'work'}} passing a single dict instead of a list of dicts; {'AND': ({'a':{'eq':1}},)} tuple; {'AND': 'user_id=u1'} string; building AND dynamically and appending zero elements or wrapping incorrectly.
Common situations: Migrating Mongo-style $and (which also expects a list but often appears as a dict in hand-written code); LLM-generated filter JSON where AND maps to an object; functools.reduce-style filter builders producing dicts.
Related errors
- OR operator requires a non-empty list of conditions
- NOT operator requires a non-empty list of conditions
- filters must contain at least one of: user_id, agent_id, run
- Invalid filter key: ${key}
- Filter value for ${key} must be str, int, float, or bool, go
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/59fc4642d3cb72d3.
Report an issue: GitHub.