{"record":{"id":"a50af8a208f3ae7b","repo":"mem0ai/mem0","slug":"not-filter-value-must-be-an-array","errorCode":null,"errorMessage":"$not filter value must be an array.","messagePattern":"\\$not filter value must be an array\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/neptune_analytics.ts","lineNumber":509,"sourceCode":"      if (key === \"$and\" || key === \"$or\") {\n        if (!Array.isArray(value)) {\n          throw new Error(`${key} filter value must be an array.`);\n        }\n\n        const nested = value\n          .map((entry) => this.buildMetadataVertexFilter(entry))\n          .filter((entry): entry is NeptuneVertexFilter => !!entry);\n        const joiner = key === \"$and\" ? \"andAll\" : \"orAll\";\n        const combined = this.combineVertexFilters(joiner, nested);\n        if (combined) {\n          operations.push(combined);\n        }\n        continue;\n      }\n\n      if (key === \"$not\") {\n        if (!Array.isArray(value)) {\n          throw new Error(\"$not filter value must be an array.\");\n        }\n\n        const nested = value\n          .map((entry) => this.buildMetadataVertexFilter(entry))\n          .filter((entry): entry is NeptuneVertexFilter => !!entry)\n          .map((entry) => this.negateVertexFilter(entry));\n        const combined = this.combineVertexFilters(\"andAll\", nested);\n        if (combined) {\n          operations.push(combined);\n        }\n        continue;\n      }\n\n      operations.push(this.buildFieldVertexFilter(key, value));\n    }\n\n    return this.combineVertexFilters(\"andAll\", operations);\n  }","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/neptune_analytics.ts#L491-L527","documentation":"The $not operator in the Neptune Analytics provider must be an array of sub-filters: each entry is built, then negated via negateVertexFilter, and combined with andAll (i.e., none of the entries may match). A non-array value cannot be mapped/negated, so the store throws with a specific message distinguishing it from the $and/$or guard.","triggerScenarios":"search(q, k, { $not: { user_id: 'u1' } }) instead of { $not: [{ user_id: 'u1' }] }; nested structures like { $and: [{ $not: { tag: 'x' } }] } where the inner $not value is a dict.","commonSituations":"Mongo-style $not: { $eq: value } habits; filter trees generated programmatically where single-element arrays got unwrapped.","solutions":["Wrap in an array: { $not: [{ user_id: 'u1' }] }.","Keep nesting consistent when composing: every $and/$or/$not node's value is an array of nodes.","Add a recursive assertValidNeptuneFilter() in shared code paths."],"exampleFix":"// before\nstore.search(q, 5, { $not: { user_id: 'u1' } }); // throws\n\n// after\nstore.search(q, 5, { $not: [{ user_id: 'u1' }] });","handlingStrategy":"validation","validationCode":"if (filters.$not !== undefined && !Array.isArray(filters.$not)) {\n  filters = { ...filters, $not: [filters.$not] };\n}","typeGuard":"const isNotArray = (v: unknown): v is NeptuneFilters[] => Array.isArray(v) && v.length > 0;","tryCatchPattern":"try { await store.search(q, 5, filters); }\ncatch (e) {\n  if (e instanceof Error && e.message === '$not filter value must be an array.') {\n    return store.search(q, 5, { ...filters, $not: [filters.$not] });\n  }\n  throw e;\n}","preventionTips":["$not takes an array, same as $and/$or — write it that way from the start.","Avoid Mongo-style $not: { $eq: x }; use { $not: [{ field: x }] }.","Validate the whole $-tree shape once in shared filter-normalization code."],"tags":["neptune","filters","validation","vector-store","aws"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}