mem0ai/mem0 · error · Error
Filter value for '${key}' must be a scalar (string, number,
Error message
Filter value for '${key}' must be a scalar (string, number, boolean), not an object. Objects may contain MongoDB query operators. What it means
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.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/mongodb.ts:200
}
}
private validateFilterValue(key: string, value: any): void {
if (typeof value === "object" && value !== null) {
if (Array.isArray(value)) {
for (const item of value) {
if (
typeof item === "object" &&
item !== null &&
!Array.isArray(item)
) {
throw new Error(
`Filter list for '${key}' contains an object, which may contain MongoDB query operators.`,
);
}
}
} else {
throw new Error(
`Filter value for '${key}' must be a scalar (string, number, boolean), not an object. Objects may contain MongoDB query operators.`,
);
}
}
}
async insert(
vectors: number[][],
ids: string[],
payloads: Record<string, any>[],
): Promise<void> {
await this.initialize();
const documents = vectors.map((vector, idx) => ({
_id: ids[idx] as any,
embedding: vector,
payload: payloads[idx] || {},
}));View on GitHub (pinned to 001c235229)
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[].
Example fix
// before
store.search(q, 5, { user_id: { $eq: 'u1' } }); // throws
// after
store.search(q, 5, { user_id: 'u1' }); Defensive patterns
Strategy: type-guard
Validate before calling
for (const [k, v] of Object.entries(filters || {})) {
if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
throw new Error(`Filter '${k}' must be scalar, got object`);
}
} Type guard
const isMongoSafeFilters = (f: unknown): f is Record<string, string | number | boolean | (string | number | boolean)[]> =>
!!f && typeof f === 'object' && Object.values(f).every(
(v) => ['string', 'number', 'boolean'].includes(typeof v) || (Array.isArray(v) && v.every((i) => ['string', 'number', 'boolean'].includes(typeof i)))
); Try / catch
try { await store.search(q, 5, filters); }
catch (e) {
if (e instanceof Error && e.message.includes('must be a scalar')) {
// flatten { $eq: x } to x, serialize Dates to ISO strings, retry
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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 } } }).
Common situations: 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.
Related errors
- Filter list for '${key}' contains an object, which may conta
- Filter value for {key!r} must be a scalar (str, int, float,
- Filter list for {key!r} contains a dict, which may contain M
- Invalid filter key: ${JSON.stringify(key)}
- Invalid filter key: ${JSON.stringify(key)}
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/09fae3d91a46e8c6.
Report an issue: GitHub.