{"record":{"id":"9870b7bfb955a755","repo":"mem0ai/mem0","slug":"key-filter-list-item-at-index-i-must-be-a-di","errorCode":null,"errorMessage":"${key} filter list item at index ${i} must be a dict, got ${typeof item}","messagePattern":"(.+?) filter list item at index (.+?) must be a dict, got (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/qdrant.ts","lineNumber":246,"sourceCode":"    const should: (QdrantCondition | QdrantFilter)[] = [];\n    const mustNot: (QdrantCondition | QdrantFilter)[] = [];\n\n    for (const [key, value] of Object.entries(normalized)) {\n      // Handle logical operators\n      if (key === \"AND\" || key === \"OR\" || key === \"NOT\") {\n        if (!Array.isArray(value)) {\n          throw new Error(\n            `${key} filter value must be a list of filter dicts, got ${typeof value}`,\n          );\n        }\n        for (let i = 0; i < value.length; i++) {\n          const item = value[i];\n          if (\n            typeof item !== \"object\" ||\n            item === null ||\n            Array.isArray(item)\n          ) {\n            throw new Error(\n              `${key} filter list item at index ${i} must be a dict, got ${typeof item}`,\n            );\n          }\n        }\n\n        if (key === \"AND\") {\n          for (const sub of value) {\n            const built = this.createFilter(sub);\n            if (built) {\n              must.push(built);\n            }\n          }\n        } else if (key === \"OR\") {\n          for (const sub of value) {\n            const built = this.createFilter(sub);\n            if (built) {\n              should.push(built);\n            }","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/qdrant.ts#L228-L264","documentation":"Each element of an AND/OR/NOT array in a Qdrant filter must itself be a filter object (dict). If a list item is a primitive, null, or an array, this error reports the offending index. It prevents building an invalid Qdrant filter that would fail opaquely server-side.","triggerScenarios":"filters: { AND: [ { a: 1 }, 'b' ] }, { OR: [ null ] }, or { NOT: [ ['a','b'] ] } — any logical list containing a non-object item.","commonSituations":"Spreading mixed content into a conditions array ({ AND: [...conds, someFlag] }); JSON filters from clients where a value is null; flattening nested arrays incorrectly.","solutions":["Ensure every element of AND/OR/NOT arrays is a filter object, wrapping bare values as { field: { eq: value } }","Filter out null/undefined entries before passing: conds.filter(Boolean)","Validate user-supplied filter JSON at the API boundary before forwarding it to search()"],"exampleFix":"// before\nconst r = await vs.search(vec, { filters: { OR: [ { tag: 'a' }, 'plain' ] } });\n\n// after\nconst r = await vs.search(vec, { filters: { OR: [ { tag: 'a' }, { tag: 'plain' } ] } });","handlingStrategy":"validation","validationCode":"function cleanLogicalList(items: unknown): Record<string, any>[] {\n  return (items as unknown[])\n    .filter(i => i !== null && i !== undefined)\n    .map(i => (i && typeof i === 'object' && !Array.isArray(i)) ? i : null)\n    .filter((i): i is Record<string, any> => i !== null);\n}\nfilters.AND = cleanLogicalList(filters.AND);","typeGuard":"const isFilterDict = (v: unknown): v is Record<string, any> =>\n  !!v && typeof v === 'object' && !Array.isArray(v);","tryCatchPattern":"try { await vs.search(vec, { filters }); } catch (e) { if (e instanceof Error && e.message.includes('must be a dict')) { /* drop or wrap offending items, retry */ } throw e; }","preventionTips":["Filter Boolean on condition arrays before assigning them to AND/OR/NOT","Wrap bare values as { field: { eq: value } } at construction time","Add unit tests covering single-element and null-containing logical arrays"],"tags":["qdrant","search-filters","logical-operators","validation","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}