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

  1. Split the mixed condition into separate filter dicts combined with AND: { AND: [ { ts: { gte: 1 } }, { ts: { eq: 5 } } ] }
  2. 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

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


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/58fbaeab268fcd8f. Report an issue: GitHub.