mem0ai/mem0 · error · Error
Unsupported filter operator: ${op}
Error message
Unsupported filter operator: ${op} What it means
When a pgvector SearchFilters value is an object, each key inside it is treated as a comparison operator and looked up in OPERATOR_SQL_MAP. An operator not present in that map throws 'Unsupported filter operator'. Supported operators are those mapped for SQL (eq, ne, gt, gte, lt, lte, in, nin, contains, icontains, etc.).
Source
Thrown at mem0-ts/src/oss/src/vector_stores/pgvector.ts:118
conditions.push("NOT (" + notGroups.join(" OR ") + ")");
}
continue;
}
const safeKey = escapeFilterKey(key);
if (value === "*") {
conditions.push(`payload ? $${paramIndex}`);
values.push(key);
paramIndex++;
continue;
}
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
for (const [op, opValue] of Object.entries(value)) {
const mapping = OPERATOR_SQL_MAP[op];
if (!mapping) {
throw new Error(`Unsupported filter operator: ${op}`);
}
const clause = mapping.template
.replace("%KEY%", safeKey)
.replace("%IDX%", String(paramIndex));
conditions.push(clause);
if (op === "in" || op === "nin") {
values.push((opValue as any[]).map(String));
} else if (op === "contains" || op === "icontains") {
const escaped = String(opValue)
.replace(/\\/g, "\\\\")
.replace(/%/g, "\\%")
.replace(/_/g, "\\_");
values.push(`%${escaped}%`);
} else if (mapping.numeric) {
values.push(Number(opValue));
} else {
values.push(String(opValue));View on GitHub (pinned to 001c235229)
Solutions
- Correct the operator name to a supported one: eq, ne, gt, gte, lt, lte, in, nin, contains, icontains
- Remove the $ prefix if using Mongo-style operators ('$gte' -> 'gte')
- For operators like 'between', rewrite as two range conditions combined with AND
Example fix
// before
const r = await vs.search(embedding, { filters: { ts: { $gte: 5 } } });
// after
const r = await vs.search(embedding, { filters: { ts: { gte: 5 } } }); Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED = new Set(['eq','ne','gt','gte','lt','lte','in','nin','contains','icontains']);
function validateOperators(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 (!SUPPORTED.has(op)) throw new Error(`Unsupported operator: ${op}`);
}
}
}
}
validateOperators(filters); Type guard
const isSupportedOperator = (op: string): op is 'eq'|'ne'|'gt'|'gte'|'lt'|'lte'|'in'|'nin'|'contains'|'icontains' => ['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.startsWith('Unsupported filter operator')) { /* strip/replace bad op, retry once */ } throw e; } Prevention
- Type your filters with a shared FilterOperators union so invalid operators fail at compile time
- Do not copy operator syntax between vector store backends — supported sets differ
- Validate externally supplied filter JSON before it reaches the store
When it happens
Trigger: Passing a nested operator object with a typo or unsupported operator, e.g. filters: { ts: { gteq: 5 } }, { tag: { has: 'x' } }, or { f: { between: [1,2] } } — any object-valued filter whose keys are not recognized comparison operators.
Common situations: Typos like 'gteq' or 'lteq'; copying filter syntax from another vector DB (Qdrant/Weaviate style operators) into the pgvector store; assuming Mongo-style '$gte' works here.
Related errors
- Invalid filter key '${key}': only letters, digits, and under
- Unsupported filter operator '${op}' for Pinecone
- Cannot mix range operators (${ops.filter((o) => rangeOps.inc
- Unsupported filter operator(s) for field '${key}': ${ops.joi
- Invalid ${label} '${name}': only letters, digits, and unders
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/e91ea81d82a2a371.
Report an issue: GitHub.