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

  1. Wrap conditions in a list: {'AND': [cond1, cond2]} with each condition its own dict.
  2. If there is only one condition, skip AND entirely: just use {'a': {'gte': 1}}.
  3. When building programmatically, accumulate a list: conds.append({...}) then filters={'AND': conds} only if len(conds) > 1.
  4. 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

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


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/59fc4642d3cb72d3. Report an issue: GitHub.