{"record":{"id":"09fae3d91a46e8c6","repo":"mem0ai/mem0","slug":"filter-value-for-key-must-be-a-scalar-string","errorCode":null,"errorMessage":"Filter value for '${key}' must be a scalar (string, number, boolean), not an object. Objects may contain MongoDB query operators.","messagePattern":"Filter value for '(.+?)' must be a scalar \\(string, number, boolean\\), not an object\\. Objects may contain MongoDB query operators\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/mongodb.ts","lineNumber":200,"sourceCode":"    }\n  }\n\n  private validateFilterValue(key: string, value: any): void {\n    if (typeof value === \"object\" && value !== null) {\n      if (Array.isArray(value)) {\n        for (const item of value) {\n          if (\n            typeof item === \"object\" &&\n            item !== null &&\n            !Array.isArray(item)\n          ) {\n            throw new Error(\n              `Filter list for '${key}' contains an object, which may contain MongoDB query operators.`,\n            );\n          }\n        }\n      } else {\n        throw new Error(\n          `Filter value for '${key}' must be a scalar (string, number, boolean), not an object. Objects may contain MongoDB query operators.`,\n        );\n      }\n    }\n  }\n\n  async insert(\n    vectors: number[][],\n    ids: string[],\n    payloads: Record<string, any>[],\n  ): Promise<void> {\n    await this.initialize();\n\n    const documents = vectors.map((vector, idx) => ({\n      _id: ids[idx] as any,\n      embedding: vector,\n      payload: payloads[idx] || {},\n    }));","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/mongodb.ts#L182-L218","documentation":"A non-array object filter value is rejected by the MongoDB provider because MongoDB would parse it as a query-operator expression ({ user_id: { $gt: 'a' } }), enabling NoSQL injection and unpredictable queries. Only scalars (string, number, boolean) are allowed as direct values. The error names the offending key so the caller can locate the bad field.","triggerScenarios":"search(query, topK, { user_id: { $eq: 'u1' } }); { ts: { $gte: 123 } }; null/Date/Buffer values typed as object; filters built by spreading nested objects ({ ...{ meta: { deep: 1 } } }).","commonSituations":"Porting raw MongoDB find() queries into SearchFilters; user-supplied JSON filters passed through unvalidated; Date objects (typeof 'object') used as filter values instead of ISO strings or timestamps.","solutions":["Use flat equality: { user_id: 'u1', active: true }.","Serialize Dates to string/number before filtering: { created_at: date.toISOString() }.","Enforce a zod/schema check on external filter input allowing only string|number|boolean|scalar[]."],"exampleFix":"// before\nstore.search(q, 5, { user_id: { $eq: 'u1' } }); // throws\n\n// after\nstore.search(q, 5, { user_id: 'u1' });","handlingStrategy":"type-guard","validationCode":"for (const [k, v] of Object.entries(filters || {})) {\n  if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n    throw new Error(`Filter '${k}' must be scalar, got object`);\n  }\n}","typeGuard":"const isMongoSafeFilters = (f: unknown): f is Record<string, string | number | boolean | (string | number | boolean)[]> =>\n  !!f && typeof f === 'object' && Object.values(f).every(\n    (v) => ['string', 'number', 'boolean'].includes(typeof v) || (Array.isArray(v) && v.every((i) => ['string', 'number', 'boolean'].includes(typeof i)))\n  );","tryCatchPattern":"try { await store.search(q, 5, filters); }\ncatch (e) {\n  if (e instanceof Error && e.message.includes('must be a scalar')) {\n    // flatten { $eq: x } to x, serialize Dates to ISO strings, retry\n  } else throw e;\n}","preventionTips":["Flatten Mongo-style operator objects to plain equality before calling search().","Serialize Dates to ISO strings/timestamps; Date is typeof 'object' and will be rejected.","Treat any object filter value from external input as a potential injection attempt and reject it."],"tags":["mongodb","filters","injection-guard","security","validation"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}