{"record":{"id":"3df2ebd007542856","repo":"mem0ai/mem0","slug":"not-operator-requires-a-non-empty-list-of-conditio","errorCode":null,"errorMessage":"NOT operator requires a non-empty list of conditions","messagePattern":"NOT operator requires a non-empty list of conditions","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/memory/index.ts","lineNumber":2178,"sourceCode":"        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>,\n          )) {\n            Object.assign(orCondition, processCondition(subKey, subValue));\n          }\n          processedFilters[\"$or\"].push(orCondition);\n        }\n      } else if (key === \"NOT\") {\n        // Logical NOT: Pass through to vector store for implementation-specific handling\n        if (!Array.isArray(value) || value.length === 0) {\n          throw new Error(\n            \"NOT operator requires a non-empty list of conditions\",\n          );\n        }\n        processedFilters[\"$not\"] = [];\n        for (const condition of value) {\n          const notCondition: Record<string, any> = {};\n          for (const [subKey, subValue] of Object.entries(\n            condition as Record<string, any>,\n          )) {\n            Object.assign(notCondition, processCondition(subKey, subValue));\n          }\n          processedFilters[\"$not\"].push(notCondition);\n        }\n      } else {\n        Object.assign(processedFilters, processCondition(key, value));\n      }\n    }\n","sourceCodeStart":2160,"sourceCodeEnd":2196,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/memory/index.ts#L2160-L2196","documentation":"Thrown during metadata filter preprocessing when the NOT key's value is not an array or is an empty array. Like OR, NOT is passed through to the vector store as a $not list; an empty or non-list value is rejected before the query is built. Structurally identical to the OR guard.","triggerScenarios":"Writing NOT: {} or NOT: [], or a dynamically built exclusion list that ended up empty.","commonSituations":"Exclusion lists (blocked tags, muted users) that are usually populated but empty in some environments; using an object instead of an array by analogy with nested JSON filters.","solutions":["Provide a non-empty array: NOT: [{ tag: { equals: 'internal' } }]","Omit the NOT key when the exclusion list is empty","Share a helper that only adds AND/OR/NOT keys when their condition arrays are non-empty"],"exampleFix":"// before\nfilters: { user_id: 'u1', NOT: [] }\n\n// after\nconst notConds = blocked.map(b => ({ tag: { equals: b } }));\nconst filters = { user_id: 'u1', ...(notConds.length ? { NOT: notConds } : {}) };","handlingStrategy":"type-guard","validationCode":"function notKey(conds: unknown[]) { return Array.isArray(conds) && conds.length ? { NOT: conds } : {}; }","typeGuard":"const isNonEmptyConditionArray = (v: unknown): v is object[] =>\n  Array.isArray(v) && v.length > 0 && v.every((c) => typeof c === 'object' && c !== null);","tryCatchPattern":null,"preventionTips":["Only include NOT when the exclusion list has entries","Share one helper for AND/OR/NOT that drops empty lists before calling the SDK"],"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"}