{"record":{"id":"fb772a6738fb74f2","repo":"mem0ai/mem0","slug":"unsupported-filter-operator-operator","errorCode":null,"errorMessage":"Unsupported filter operator: ${operator}","messagePattern":"Unsupported filter operator: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/opensearch.ts","lineNumber":618,"sourceCode":"            range: {\n              [this.payloadField(key, false)]: {\n                [operator]: operatorValue,\n              },\n            },\n          };\n        case \"contains\":\n        case \"icontains\":\n          this.assertScalarValue(key, operatorValue);\n          return {\n            wildcard: {\n              [this.payloadField(key, true)]: {\n                value: `*${escapeWildcard(String(operatorValue))}*`,\n                case_insensitive: operator === \"icontains\",\n              },\n            },\n          };\n        default:\n          throw new Error(`Unsupported filter operator: ${operator}`);\n      }\n    });\n\n    return clauses.length === 1 ? clauses[0] : { bool: { filter: clauses } };\n  }\n\n  private payloadField(key: string, keyword: boolean): string {\n    if (key.startsWith(\"payload.\")) {\n      return keyword && !key.endsWith(\".keyword\") ? `${key}.keyword` : key;\n    }\n\n    const field = `payload.${key}`;\n    return keyword ? `${field}.keyword` : field;\n  }\n\n  // Filter values become OpenSearch term/terms/range/wildcard leaves. Allowing\n  // an object here lets a caller inject raw query parameters (e.g. a `term`\n  // object form with `boost`/`case_insensitive`), so reject non-scalar leaves.","sourceCodeStart":600,"sourceCodeEnd":636,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/opensearch.ts#L600-L636","documentation":"The OpenSearch filter builder compiles each operator into a specific query leaf (term, terms, range, wildcard). Unknown operator keys fall to a default case that throws, because no equivalent OpenSearch clause is defined and silently ignoring the operator would return unfiltered (over-broad) results.","triggerScenarios":"Using an operator this store does not implement, e.g. { field: { ne: 'x' } }, { field: { endsWith: 'y' } }, or wrong casing like { Contains: 'x' }.","commonSituations":"Sharing one filter schema across vector stores with different operator sets; typos or casing errors; new operators added to the Python SDK before the TS OpenSearch store.","solutions":["Replace unsupported operators: ne -> nin: [value]; endsWith -> contains + client-side check.","Verify operator spelling/casing against the supported list (eq/gt/gte/lt/lte/in/nin/contains/icontains/startsWith and boolean/range forms).","Keep per-backend filter builders instead of one shared schema across stores."],"exampleFix":"// before\nfilters = { status: { ne: 'deleted' } };\n\n// after\nfilters = { status: { nin: ['deleted'] } };","handlingStrategy":"validation","validationCode":"const OPS = new Set(['in','nin','contains','icontains','startsWith','gt','gte','lt','lte']);\nfor (const [field, ops] of Object.entries(fieldFilters)) {\n  for (const op of Object.keys(ops || {})) {\n    if (!OPS.has(op)) throw new TypeError(`Operator '${op}' not supported on field '${field}'`);\n  }\n}","typeGuard":"const isOpenSearchOp = (op: string): boolean => OPS.has(op);","tryCatchPattern":"catch (e) { if (e.message.includes('Unsupported filter operator')) { /* map to nin/contains and retry */ } }","preventionTips":["Keep per-store operator allow-lists","Use nin instead of ne","Check operator casing (startsWith camelCase)"],"tags":["opensearch","filters","unsupported-operation","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}