{"record":{"id":"ff91d98eb8402cfc","repo":"mem0ai/mem0","slug":"s3-vectors-does-not-support-operator-metadata","errorCode":null,"errorMessage":"S3 Vectors does not support '${operator}' metadata filters.","messagePattern":"S3 Vectors does not support '(.+?)' metadata filters\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/s3_vectors.ts","lineNumber":636,"sourceCode":"        case \"lte\":\n          operators.$lte = operand;\n          break;\n        case \"in\":\n          if (!Array.isArray(operand) || operand.length === 0) {\n            return { [ALWAYS_FALSE_FILTER_KEY]: true };\n          }\n          operators.$in = operand;\n          break;\n        case \"nin\":\n          if (!Array.isArray(operand) || operand.length === 0) {\n            break;\n          }\n          operators.$nin = operand;\n          break;\n        case \"contains\":\n        case \"icontains\":\n        case \"startsWith\":\n          throw new Error(\n            `S3 Vectors does not support '${operator}' metadata filters.`,\n          );\n        default:\n          throw new Error(\n            `Unsupported S3 Vectors filter operator: ${operator}`,\n          );\n      }\n    }\n\n    if (Object.keys(operators).length === 0) {\n      return {};\n    }\n    return { [key]: operators };\n  }\n\n  private negateFilter(filter: S3Filter): S3Filter {\n    if (Array.isArray(filter.$and)) {\n      return {","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/s3_vectors.ts#L618-L654","documentation":"The S3 Vectors vector store in mem0-ts throws this when converting a user-supplied metadata filter that uses the 'contains', 'icontains', or 'startsWith' operators. AWS S3 Vectors only supports equality, comparison, in/nin, and exists semantics on metadata, so substring matching cannot be pushed down to the service. The store fails fast at filter-conversion time instead of silently returning wrong results.","triggerScenarios":"Calling memory.search(query, { filters: { user_id: { contains: 'alice' } } }) or any filter using contains/icontains/startsWith while vectorStore is configured as S3Vectors. Also triggered when an LLM-derived filter or upstream code constructs those operators generically across vector stores.","commonSituations":"Porting an app from Qdrant/Chroma (which support substring filters) to S3 Vectors; sharing filter-building code across multiple store backends; agent pipelines that auto-generate filters with string-matching operators.","solutions":["Rewrite the filter using supported operators: in/nin for value sets, eq/ne for exact matches, gte/lte/gt/lt for ranges, exists for presence.","Do substring matching client-side: search with the broadest safe filter (e.g. eq on user_id) and post-filter the returned payloads in your code.","If substring search on metadata is a hard requirement, switch to a vector store that supports it (e.g. Qdrant, Chroma) via the vectorStore config."],"exampleFix":"// before\nawait memory.search(\"notes\", { filters: { user_id: { contains: \"alice\" } } });\n\n// after\nconst results = await memory.search(\"notes\", { filters: { user_id: { eq: \"alice-123\" } } });","handlingStrategy":"validation","validationCode":"const S3_UNSUPPORTED = new Set([\"contains\", \"icontains\", \"startsWith\"]);\nfunction assertS3SafeFilter(filters: any): void {\n  for (const [k, v] of Object.entries(filters ?? {})) {\n    if ([\"AND\", \"OR\", \"NOT\"].includes(k)) { (v as any[]).forEach(assertS3SafeFilter); continue; }\n    if (v && typeof v === \"object\" && !Array.isArray(v))\n      for (const op of Object.keys(v))\n        if (S3_UNSUPPORTED.has(op)) throw new Error(`Filter operator '${op}' unsupported on S3 Vectors; rewrite as in/eq`);\n  }\n}\nassertS3SafeFilter(myFilters);","typeGuard":"function isS3SafeOperator(op: string): op is 'eq'|'ne'|'gt'|'gte'|'lt'|'lte'|'in'|'nin' {\n  return ['eq','ne','gt','gte','lt','lte','in','nin'].includes(op);\n}","tryCatchPattern":"try { await memory.search(q, { filters }); } catch (e) { if (e instanceof Error && e.message.includes('does not support') && e.message.includes('metadata filters')) { /* fall back to eq filter + client-side substring */ } else throw e; }","preventionTips":["Keep per-store filter profiles when multi-backend","Prefer in/nin over substring operators for portable filters","Post-filter payloads client-side for text matching"],"tags":["s3-vectors","filters","metadata","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}