{"record":{"id":"1e920c48afbc6e55","repo":"mem0ai/mem0","slug":"neptune-analytics-cannot-negate-this-filter-shape","errorCode":null,"errorMessage":"Neptune Analytics cannot negate this filter shape for vector search.","messagePattern":"Neptune Analytics cannot negate this filter shape for vector search\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/neptune_analytics.ts","lineNumber":732,"sourceCode":"    if (filter.lessThanOrEquals) {\n      return {\n        greaterThan: filter.lessThanOrEquals,\n      };\n    }\n\n    if (filter.in) {\n      return {\n        notIn: filter.in,\n      };\n    }\n\n    if (filter.notIn) {\n      return {\n        in: filter.notIn,\n      };\n    }\n\n    throw new Error(\n      \"Neptune Analytics cannot negate this filter shape for vector search.\",\n    );\n  }\n\n  private buildWhereClause(\n    filters?: SearchFilters,\n    startIndex: number = 1,\n  ): WhereClauseResult {\n    const clauses: string[] = [];\n    const parameters: Record<string, any> = {};\n    let nextIndex = startIndex;\n\n    for (const [key, value] of Object.entries(filters || {})) {\n      if (value === undefined) {\n        continue;\n      }\n\n      if (key === \"$and\" || key === \"$or\") {","sourceCodeStart":714,"sourceCodeEnd":750,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/neptune_analytics.ts#L714-L750","documentation":"negateVertexFilter() implements De Morgan transformation only for shapes it can invert: andAll/orAll compositions, in, and notIn. If a $not wraps a filter shape it cannot negate (e.g. startsWith, contains, or a combined eq shape with no inverse mapping), it throws rather than emitting a filter with incorrect semantics.","triggerScenarios":"{ $not: [{ name: { startsWith: 'test-' } }] } or { $not: [{ data: { contains: 'x' } }] } on the neptune-analytics provider; nested $not inside $and/$or trees where the inner entries hit the unhandled shapes.","commonSituations":"Exclusion filters for prefix or substring matching; machine-generated filter trees that wrap arbitrary leaves in $not.","solutions":["Move the negation to supported leaves: negate equality ({ field: 'x' } under $not) or membership (in).","Post-filter client-side: fetch with the positive filter removed, then exclude matching payloads in JS.","Restructure: use notIn lists instead of $not over startsWith/contains."],"exampleFix":"// before\nstore.search(q, 20, { $not: [{ name: { startsWith: 'test-' } }] }); // throws\n\n// after\nconst res = await store.search(q, 20);\nconst filtered = res.filter(r => !r.payload?.name?.startsWith('test-'));","handlingStrategy":"fallback","validationCode":"function isNegatableShape(node: any): boolean {\n  if (Array.isArray(node.$and) || Array.isArray(node.$or)) return node.$and?.every(isNegatableShape) ?? node.$or?.every(isNegatableShape) ?? true;\n  const v = Object.values(node)[0];\n  if (v && typeof v === 'object' && !Array.isArray(v)) {\n    const op = Object.keys(v)[0];\n    return op === 'in' || op === 'notIn' || op === 'eq'; // only these have inverses\n  }\n  return true; // plain equality is negatable\n}","typeGuard":"type NegatableFilter =\n  | { in: { property: string; value: (string | number)[] } }\n  | { notIn: { property: string; value: (string | number)[] } }\n  | { andAll: NegatableFilter[] }\n  | { orAll: NegatableFilter[] };","tryCatchPattern":"try { results = await store.search(q, k, filters); }\ncatch (e) {\n  if (e instanceof Error && e.message.includes('cannot negate this filter shape')) {\n    // fallback: search without the $not clause, exclude matches client-side\n    const positive = removeNotClauses(filters);\n    const wide = await store.search(q, k, positive);\n    results = applyNotClientSide(wide, filters.$not);\n  } else throw e;\n}","preventionTips":["Only negate in/notIn/equality leaves under $not; startsWith/contains have no Neptune inverse.","Prefer notIn lists over $not of complex shapes.","Test every filter tree shape you generate against the Neptune provider in CI."],"tags":["neptune","filters","unsupported-operation","negation","vector-store"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}