{"record":{"id":"59fc4642d3cb72d3","repo":"mem0ai/mem0","slug":"and-operator-requires-a-list-of-conditions-59fc46","errorCode":null,"errorMessage":"AND operator requires a list of conditions","messagePattern":"AND operator requires a list of conditions","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mem0/memory/main.py","lineNumber":1571,"sourceCode":"                if operator in operator_map:\n                    result.setdefault(key, {})[operator_map[operator]] = value\n                else:\n                    raise ValueError(f\"Unsupported metadata filter operator: {operator}\")\n            return result\n\n        def merge_filters(target: Dict[str, Any], source: Dict[str, Any]) -> None:\n            \"\"\"Merge source into target, deep-merging nested operator dicts for the same key.\"\"\"\n            for key, value in source.items():\n                if key in target and isinstance(target[key], dict) and isinstance(value, dict):\n                    target[key].update(value)\n                else:\n                    target[key] = value\n\n        for key, value in metadata_filters.items():\n            if key == \"AND\":\n                # Logical AND: combine multiple conditions\n                if not isinstance(value, list):\n                    raise ValueError(\"AND operator requires a list of conditions\")\n                for condition in value:\n                    for sub_key, sub_value in condition.items():\n                        merge_filters(processed_filters, process_condition(sub_key, sub_value))\n            elif key == \"OR\":\n                # Logical OR: Pass through to vector store for implementation-specific handling\n                if not isinstance(value, list) or not value:\n                    raise ValueError(\"OR operator requires a non-empty list of conditions\")\n                # Store OR conditions in a way that vector stores can interpret\n                processed_filters[\"$or\"] = []\n                for condition in value:\n                    or_condition = {}\n                    for sub_key, sub_value in condition.items():\n                        merge_filters(or_condition, process_condition(sub_key, sub_value))\n                    processed_filters[\"$or\"].append(or_condition)\n            elif key == \"NOT\":\n                # Logical NOT: Pass through to vector store for implementation-specific handling\n                if not isinstance(value, list) or not value:\n                    raise ValueError(\"NOT operator requires a non-empty list of conditions\")","sourceCodeStart":1553,"sourceCodeEnd":1589,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0/memory/main.py#L1553-L1589","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nfilters = {\"AND\": {\"user_id\": \"u1\", \"tag\": \"work\"}}\n\n# after\nfilters = {\"AND\": [{\"user_id\": \"u1\"}, {\"tag\": \"work\"}]}","handlingStrategy":"validation","validationCode":"if \"AND\" in filters and not isinstance(filters[\"AND\"], list):\n    filters[\"AND\"] = [filters[\"AND\"]]  # or raise your own error","typeGuard":"def is_valid_logical_filter(key: str, value) -> bool:\n    if key == \"AND\":\n        return isinstance(value, list)\n    return isinstance(value, list) and len(value) > 0  # OR / NOT","tryCatchPattern":null,"preventionTips":["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."],"tags":["validation","filters","logical-operators","search"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}