{"record":{"id":"1ec831f391bd8473","repo":"mem0ai/mem0","slug":"and-filter-value-must-be-a-list-of-filter-dicts-g","errorCode":null,"errorMessage":"AND filter value must be a list of filter dicts, got ${typeof value}","messagePattern":"AND filter value must be a list of filter dicts, got (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/cassandra.ts","lineNumber":542,"sourceCode":"    }\n\n    const keyMap: Record<string, string> = {\n      $and: \"AND\",\n      $or: \"OR\",\n      $not: \"NOT\",\n    };\n    const normalized: Record<string, any> = {};\n    for (const [key, value] of Object.entries(filters)) {\n      const normalizedKey = keyMap[key] || key;\n      if (!(normalizedKey in normalized)) {\n        normalized[normalizedKey] = value;\n      }\n    }\n\n    for (const [key, value] of Object.entries(normalized)) {\n      if (key === \"AND\") {\n        if (!Array.isArray(value)) {\n          throw new Error(\n            `AND filter value must be a list of filter dicts, got ${typeof value}`,\n          );\n        }\n        if (\n          !value.every((entry: SearchFilters) =>\n            this.filterVector(vector, entry),\n          )\n        ) {\n          return false;\n        }\n      } else if (key === \"OR\") {\n        if (!Array.isArray(value)) {\n          throw new Error(\n            `OR filter value must be a list of filter dicts, got ${typeof value}`,\n          );\n        }\n        if (\n          !value.some((entry: SearchFilters) =>","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/cassandra.ts#L524-L560","documentation":"The Cassandra store filters vectors in memory via filterVector(). An 'AND' key must map to an array of filter objects so each entry can be evaluated and ANDed together. Passing an object (or any non-array) instead throws immediately with the offending JS type.","triggerScenarios":"Calling search/list/getAll with filters like { AND: { user_id: 'x' } } (a single dict) or { AND: 'user_id=x' } (a string) instead of { AND: [{ user_id: 'x' }, { run_id: 'y' }] }.","commonSituations":"Assuming AND takes a single combined object because other filter keys do; converting filters from another store's DSL where AND is an object; hand-building filters from dynamic code that collapses arrays.","solutions":["Wrap the AND value in an array: { AND: [{ user_id: 'x' }, { run_id: 'y' }] }","If a single condition, either put it at the top level ({ user_id: 'x' }) or wrap it as a one-element array"],"exampleFix":"// before\nmemory.search('query', { filters: { AND: { user_id: 'u1', run_id: 'r1' } } });\n\n// after\nmemory.search('query', { filters: { AND: [{ user_id: 'u1' }, { run_id: 'r1' }] } });","handlingStrategy":"type-guard","validationCode":"function isFilterDictArray(v: unknown): v is Record<string, any>[] {\n  return Array.isArray(v) && v.every((e) => e && typeof e === 'object' && !Array.isArray(e));\n}\nif (filters.AND && !isFilterDictArray(filters.AND)) throw new Error('AND must be an array of filter dicts');","typeGuard":"const isFilterDictArray = (v: unknown): v is Record<string, any>[] =>\n  Array.isArray(v) && v.every((e) => e !== null && typeof e === 'object' && !Array.isArray(e));","tryCatchPattern":null,"preventionTips":["Centralize filter construction in one helper that always emits arrays for AND/OR/NOT","Add unit tests asserting the array shape for combinator filters"],"tags":["cassandra","filters","validation","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}