{"record":{"id":"cb566dcfe38f0782","repo":"mem0ai/mem0","slug":"filter-value-for-key-must-be-an-array","errorCode":null,"errorMessage":"Filter value for '${key}' must be an array.","messagePattern":"Filter value for '(.+?)' must be an array\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/opensearch.ts","lineNumber":649,"sourceCode":"    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.\n  // Mirrors the Python SDK's `_validate_filter` scalar allow-list (PR #5986).\n  private assertScalarValue(key: string, value: any): void {\n    if (value !== null && typeof value === \"object\") {\n      throw new Error(\n        `Filter value for '${key}' must be a string, number, or boolean, got ` +\n          `${Array.isArray(value) ? \"an array\" : \"an object\"}.`,\n      );\n    }\n  }\n\n  private assertScalarArray(key: string, value: any): void {\n    if (!Array.isArray(value)) {\n      throw new Error(`Filter value for '${key}' must be an array.`);\n    }\n    value.forEach((item) => this.assertScalarValue(key, item));\n  }\n}\n","sourceCodeStart":631,"sourceCodeEnd":654,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/opensearch.ts#L631-L654","documentation":"Operators that compare against a set (in / nin) compile to OpenSearch terms queries and therefore require their filter value to be an array. assertScalarArray both checks that the value is an array and validates every element is scalar, throwing this message when the array itself is missing.","triggerScenarios":"Passing { tag: { in: 'prod' } } (scalar instead of array) or { tag: { nin: { env: 'prod' } } } to search/list filters on the OpenSearch store.","commonSituations":"Accepting a single value from user input and not normalizing to array; config files that collapse one-element lists; porting from backends that accept a scalar for membership tests.","solutions":["Always pass an array for in/nin: { tag: { in: ['prod'] } }.","Normalize input: const arr = Array.isArray(v) ? v : [v]; before building the filter.","Add a type guard on user-supplied filter values before calling search."],"exampleFix":"// before\nfilters = { tag: { in: 'prod' } };\n\n// after\nfilters = { tag: { in: ['prod'] } };","handlingStrategy":"validation","validationCode":"for (const [op, v] of Object.entries(ops)) {\n  if ((op === 'in' || op === 'nin') && !Array.isArray(v)) {\n    ops[op] = [v]; // normalize scalar to array\n  }\n}","typeGuard":"const isScalarArray = (v: unknown): v is (string | number | boolean)[] =>\n  Array.isArray(v) && v.every((i) => i === null || ['string','number','boolean'].includes(typeof i));","tryCatchPattern":null,"preventionTips":["Always wrap in/nin values in arrays","Normalize single user inputs to arrays","Reuse one filter-builder helper across the app"],"tags":["opensearch","filters","validation","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}