{"record":{"id":"61deb5a16ff9adc9","repo":"mem0ai/mem0","slug":"and-operator-requires-a-list-of-conditions","errorCode":null,"errorMessage":"AND operator requires a list of conditions","messagePattern":"AND operator requires a list of conditions","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/memory/index.ts","lineNumber":2151,"sourceCode":"\n      for (const [operator, value] of Object.entries(condition)) {\n        if (operator in operatorMap) {\n          if (!result[key]) {\n            result[key] = {};\n          }\n          result[key][operatorMap[operator]] = value;\n        } else {\n          throw new Error(`Unsupported metadata filter operator: ${operator}`);\n        }\n      }\n      return result;\n    };\n\n    for (const [key, value] of Object.entries(metadataFilters)) {\n      if (key === \"AND\") {\n        // Logical AND: combine multiple conditions\n        if (!Array.isArray(value)) {\n          throw new Error(\"AND operator requires a list of conditions\");\n        }\n        for (const condition of value) {\n          for (const [subKey, subValue] of Object.entries(condition)) {\n            Object.assign(processedFilters, processCondition(subKey, subValue));\n          }\n        }\n      } else if (key === \"OR\") {\n        // Logical OR: Pass through to vector store for implementation-specific handling\n        if (!Array.isArray(value) || value.length === 0) {\n          throw new Error(\n            \"OR operator requires a non-empty list of conditions\",\n          );\n        }\n        processedFilters[\"$or\"] = [];\n        for (const condition of value) {\n          const orCondition: Record<string, any> = {};\n          for (const [subKey, subValue] of Object.entries(\n            condition as Record<string, any>,","sourceCodeStart":2133,"sourceCodeEnd":2169,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/memory/index.ts#L2133-L2169","documentation":"Thrown during metadata filter preprocessing when the AND key's value is not an array. AND in this filter DSL is a list of condition objects, each processed via processCondition; a single object or a scalar cannot be combined. It fires before any vector store call.","triggerScenarios":"Writing filters: { user_id: 'u1', AND: { category: { equals: 'pref' } } } — an object instead of a list; or AND: 'category' (scalar).","commonSituations":"Copying a Mongo-style nested object (no array wrapper) from other query DSLs; forgetting the array brackets when there is only one condition.","solutions":["Wrap AND conditions in an array: AND: [{ category: { equals: 'pref' } }]","Even a single condition must be inside the list","Type your filter objects against the SDK's filter types so the compiler catches this"],"exampleFix":"// before\n{ user_id: 'u1', AND: { category: { equals: 'pref' } } }\n\n// after\n{ user_id: 'u1', AND: [{ category: { equals: 'pref' } }] }","handlingStrategy":"type-guard","validationCode":"function validAnd(v: unknown): boolean { return Array.isArray(v) && v.length > 0 && v.every(c => typeof c === 'object' && c !== null); }","typeGuard":"const isConditionList = (v: unknown): v is Record<string, Record<string, unknown>>[] =>\n  Array.isArray(v) && v.every((c) => typeof c === 'object' && c !== null);","tryCatchPattern":null,"preventionTips":["AND always takes an array, even for a single condition","Define a shared Filter type so TypeScript rejects the object form"],"tags":["validation","oss","filters","metadata"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}