mem0ai/mem0 · error · Error
Cannot mix range operators (${ops.filter((o) => rangeOps.inc
Error message
Cannot mix range operators (${ops.filter((o) => rangeOps.includes(o)).join(", ")}) with non-range operators (${nonRangeOps.join(", ")}) for field '${key}'. Use AND to combine them as separate conditions. What it means
In the Qdrant store, an object-valued filter field is converted into a single Qdrant range condition when it contains range operators (gt, gte, lt, lte). Qdrant's range model allows only one range object per field, so mixing range operators with non-range operators (eq, ne, in, nin, contains, ...) in the same object is rejected with guidance to split them into separate AND conditions.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/qdrant.ts:159
}
// Simple equality
return { key, match: { value } };
}
// Handle array shorthand: {"field": ["a", "b"]} treated as "in" operator
if (Array.isArray(value)) {
return { key, match: { any: value } };
}
const ops = Object.keys(value);
const rangeOps = ["gt", "gte", "lt", "lte"];
const hasRangeOps = ops.some((op) => rangeOps.includes(op));
const nonRangeOps = ops.filter((op) => !rangeOps.includes(op));
// Handle range operators
if (hasRangeOps) {
if (nonRangeOps.length > 0) {
throw new Error(
`Cannot mix range operators (${ops.filter((o) => rangeOps.includes(o)).join(", ")}) ` +
`with non-range operators (${nonRangeOps.join(", ")}) for field '${key}'. ` +
`Use AND to combine them as separate conditions.`,
);
}
const range: Record<string, number | string> = {};
for (const op of rangeOps) {
if (op in value) {
range[op] = value[op];
}
}
return { key, range };
}
// Handle comparison operators
if ("eq" in value) {
return { key, match: { value: value.eq } };
}View on GitHub (pinned to 001c235229)
Solutions
- Split the mixed condition into separate filter dicts combined with AND: { AND: [ { ts: { gte: 1 } }, { ts: { eq: 5 } } ] }
- Keep pure range objects ({ gte, lte }) per field and put equality checks as their own top-level filter entries
Example fix
// before
const r = await vs.search(vec, { filters: { ts: { gte: 1, eq: 5 } } });
// after
const r = await vs.search(vec, {
filters: { AND: [ { ts: { gte: 1 } }, { ts: { eq: 5 } } ] },
}); Defensive patterns
Strategy: validation
Validate before calling
const RANGE_OPS = new Set(['gt','gte','lt','lte']);
function splitMixedRangeFilters(filters: any): any {
const out: any = {};
for (const [k, v] of Object.entries(filters)) {
if (v && typeof v === 'object' && !Array.isArray(v)) {
const ops = Object.keys(v);
if (ops.some(o => RANGE_OPS.has(o)) && ops.some(o => !RANGE_OPS.has(o))) {
const range: any = {}, eqs: any[] = [];
for (const [op, val] of Object.entries(v)) {
if (RANGE_OPS.has(op)) range[op] = val; else eqs.push({ [k]: { [op]: val } });
}
out.AND = [...(out.AND ?? []), { [k]: range }, ...eqs];
continue;
}
}
out[k] = v;
}
return out;
} Type guard
const isPureRangeObject = (v: Record<string, any>): boolean => Object.keys(v).length > 0 && Object.keys(v).every(o => ['gt','gte','lt','lte'].includes(o));
Try / catch
try { await vs.search(vec, { filters }); } catch (e) { if (e instanceof Error && e.message.includes('Cannot mix range operators')) { /* split field into AND entries, retry */ } throw e; } Prevention
- One operator class per field object: pure range or pure match, never both
- Build compound predicates as AND lists from the start
- Encapsulate filter construction behind a small query-builder in your codebase
When it happens
Trigger: Filters like { ts: { gte: 1, eq: 5 } } or { price: { lt: 100, currency: 'USD' } } — any object with both a range op (gt/gte/lt/lte) and a non-range op under the same key.
Common situations: Naturally writing a compound predicate on one field ({ date: { gte: a, lte: b, ne: holiday } }); merging filter objects from multiple sources that collapse into a single key.
Related errors
- Unsupported filter operator(s) for field '${key}': ${ops.joi
- Unsupported filter operator: ${op}
- Unsupported filter operator '${op}' for Pinecone
- ${key} filter value must be a list of filter dicts, got ${ty
- ${key} filter list item at index ${i} must be a dict, got ${
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/58fbaeab268fcd8f.
Report an issue: GitHub.