mem0ai/mem0 · error · Error
Unsupported Oracle filter operator(s) for field '${metadataK
Error message
Unsupported Oracle filter operator(s) for field '${metadataKey}': ${unsupported.sort().join(", ")} What it means
Thrown while translating a MongoDB-style field filter into an Oracle JSON_EXISTS predicate. buildFieldCondition inspects the operator object for a field and rejects any operator key not in FIELD_OPERATORS (eq, ne, gt, gte, lt, lte, in, nin, contains, icontains). This guard exists because the Oracle JSON path language only supports a fixed comparison subset, so unknown operators cannot be mapped to SQL.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/oracledb.ts:156
if (Array.isArray(value)) {
throw new Error(
`Oracle filter for field '${metadataKey}' must be a scalar or an operator object`,
);
}
const operators = Object.entries(value);
if (operators.length === 0) {
throw new Error(
`Operator filter for field '${metadataKey}' must not be empty`,
);
}
const unsupported = operators
.map(([op]) => op)
.filter((op) => !FIELD_OPERATORS.has(op));
if (unsupported.length > 0) {
throw new Error(
`Unsupported Oracle filter operator(s) for field '${metadataKey}': ${unsupported.sort().join(", ")}`,
);
}
const predicates: string[] = [];
const passings: string[] = [];
const additionalClauses: string[] = [];
for (const [operator, operand] of operators) {
if (operator in COMPARISON_OPERATORS) {
if (!isScalar(operand)) {
throw new Error(
`Oracle filter operator '${operator}' requires a scalar value`,
);
}
if (operand === null) {
if (operator !== "eq" && operator !== "ne") {
throw new Error(View on GitHub (pinned to 001c235229)
Solutions
- Rewrite the filter using only supported operators: eq, ne, gt, gte, lt, lte, in, nin, contains, icontains — without the '$' prefix.
- Replace '$in' with 'in' and '$nin' with 'nin'; the Oracle adapter uses unprefixed operator names.
- Replace unsupported operators with supported equivalents: $regex → contains/icontains on strings, $exists → the '*' value (field presence check), $gt/$gte/$lt/$lte → gt/gte/lt/lte.
- Run search() without filters and post-filter in application code if the predicate cannot be expressed with the supported set.
Example fix
// before
await memory.search('query', { filters: { user_id: { $in: ['u1','u2'] } } });
// after
await memory.search('query', { filters: { user_id: { in: ['u1', 'u2'] } } }); Defensive patterns
Strategy: validation
Validate before calling
const FIELD_OPERATORS = new Set(['eq','ne','gt','gte','lt','lte','in','nin','contains','icontains']);
function validateFieldFilters(filters: any, path = 'filters'): void {
if (!filters || typeof filters !== 'object') return;
for (const [key, value] of Object.entries(filters)) {
if (key.startsWith('$') || key === 'AND' || key === 'OR' || key === 'NOT') {
if (Array.isArray(value)) value.forEach((c, i) => validateFieldFilters(c, `${path}.${key}[${i}]`));
continue;
}
if (value && typeof value === 'object' && !Array.isArray(value)) {
const bad = Object.keys(value).filter((op) => !FIELD_OPERATORS.has(op));
if (bad.length) throw new RangeError(`${path}: unsupported operators ${bad.join(', ')} on field '${key}'`);
}
}
} Type guard
function isSupportedFieldFilter(v: any): boolean {
return v !== null && typeof v === 'object' && !Array.isArray(v) &&
Object.keys(v).every((op) => ['eq','ne','gt','gte','lt','lte','in','nin','contains','icontains'].includes(op));
} Try / catch
try { await memory.search('q', { filters }); } catch (e) { if (e instanceof Error && e.message.includes('Unsupported Oracle filter operator')) { /* rewrite or drop the offending operators, retry without them */ } else throw e; } Prevention
- Keep one shared filter-builder module that only emits eq/ne/gt/gte/lt/lte/in/nin/contains/icontains.
- Strip '$' prefixes when porting Mongo-style filters: $in → in, $nin → nin.
- Add unit tests over the filter builder asserting the supported-operator set.
When it happens
Trigger: Calling search()/getAll() with filters like { user_id: { $eq: 'u1', $regex: '.*' } } — '$regex' is not in FIELD_OPERATORS and triggers the error listing '$regex'. Any filter object under a field key containing operators such as $exists, $size, $all, $elemMatch, $between, or $not (field-level) will be rejected.
Common situations: Copying filter syntax from the MongoDB docs or from another mem0 vector store backend (e.g. Qdrant/pgvector) that supports a wider operator set; using '$in' instead of the required 'in' (no dollar prefix); writing nested operator objects where a plain value was expected.
Related errors
- AND filter value must be a list of filter dicts, got ${typeo
- OR filter value must be a list of filter dicts, got ${typeof
- NOT filter value must be a list of filter dicts, got ${typeo
- AND filter value must be a list of filter dicts, got ${typeo
- OR filter value must be a list of filter dicts, got ${typeof
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/bad79cdf6235e82a.
Report an issue: GitHub.