mem0ai/mem0 · error · Error

Unsupported filter operator(s) for field '${key}': ${ops.joi

Error message

Unsupported filter operator(s) for field '${key}': ${ops.join(", ")}. Supported operators: ${supportedOps.join(", ")}

What it means

The Qdrant filter builder falls through to this error when an object-valued filter field contains operators outside the supported set: eq, ne, gt, gte, lt, lte, in, nin, contains, icontains. It exists because Qdrant's filter model has no translation for other operators.

Source

Thrown at mem0-ts/src/oss/src/vector_stores/qdrant.ts:205

    if ("contains" in value || "icontains" in value) {
      const text = value.contains || value.icontains;
      return { key, match: { text } };
    }

    // Unknown operator - treat as nested object for simple match
    const supportedOps = [
      "eq",
      "ne",
      "gt",
      "gte",
      "lt",
      "lte",
      "in",
      "nin",
      "contains",
      "icontains",
    ];
    throw new Error(
      `Unsupported filter operator(s) for field '${key}': ${ops.join(", ")}. ` +
        `Supported operators: ${supportedOps.join(", ")}`,
    );
  }

  /**
   * Create a Filter object from the provided filters.
   * Supports logical operators (AND, OR, NOT) and comparison operators.
   */
  private createFilter(filters?: SearchFilters): QdrantFilter | undefined {
    if (!filters || Object.keys(filters).length === 0) return undefined;

    // Normalize $or/$not/$and → OR/NOT/AND and deduplicate
    const normalized: Record<string, any> = {};
    for (const [key, value] of Object.entries(filters)) {
      const normKey = KEY_MAP[key] || key;
      if (!(normKey in normalized)) {
        normalized[normKey] = value;

View on GitHub (pinned to 001c235229)

Solutions

  1. Rewrite the filter using only supported operators: eq, ne, gt, gte, lt, lte, in, nin, contains, icontains
  2. Remove '$' prefixes from Mongo-style operators
  3. Express 'between' as { gte: lo, lte: hi } and 'hasAll' as a nested contains/in combination or separate AND entries

Example fix

// before
const r = await vs.search(vec, { filters: { age: { between: [20, 30] } } });

// after
const r = await vs.search(vec, { filters: { age: { gte: 20, lte: 30 } } });
Defensive patterns

Strategy: validation

Validate before calling

const QDRANT_OPS = new Set(['eq','ne','gt','gte','lt','lte','in','nin','contains','icontains']);
function validateQdrantFilters(filters: any): void {
  for (const v of Object.values(filters ?? {})) {
    if (v && typeof v === 'object' && !Array.isArray(v)) {
      for (const op of Object.keys(v)) {
        if (!QDRANT_OPS.has(op)) throw new Error(`Operator '${op}' unsupported on Qdrant`);
      }
    }
  }
}
validateQdrantFilters(filters);

Type guard

type QdrantOp = 'eq'|'ne'|'gt'|'gte'|'lt'|'lte'|'in'|'nin'|'contains'|'icontains';
const isQdrantOp = (op: string): op is QdrantOp =>
  ['eq','ne','gt','gte','lt','lte','in','nin','contains','icontains'].includes(op);

Try / catch

try { await vs.search(vec, { filters }); } catch (e) { if (e instanceof Error && e.message.includes('Unsupported filter operator')) { /* rewrite to supported ops, retry */ } throw e; }

Prevention

When it happens

Trigger: Passing filters like { f: { between: [1, 2] } }, { f: { $gte: 1 } }, { f: { hasAll: [...] } }, or an object with typo'd operator names such as { f: { gteq: 1 } }.

Common situations: Porting filter code from Mongo/Postgres syntax; typos in operator keys; combining API request payloads with extra keys inside operator objects.

Related errors


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