mem0ai/mem0 · error · Error

Operator filter for field '${metadataKey}' must not be empty

Error message

Operator filter for field '${metadataKey}' must not be empty

What it means

When a filter field value is an operator object, Object.entries(value) drives clause generation; an empty object has no operators to apply, so the resulting SQL predicate would be undefined (or accidentally always-true). The compiler throws to make the no-op filter explicit instead of producing surprising results.

Source

Thrown at mem0-ts/src/oss/src/vector_stores/oracledb.ts:147

  }

  if (isScalar(value)) {
    if (value === null) {
      return jsonExists(path, "@ == null", []);
    }
    const [variable, passing] = bindFilterValue(value, binds);
    return jsonExists(path, `@ == ${variable}`, [passing]);
  }

  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) {

View on GitHub (pinned to 001c235229)

Solutions

  1. Omit fields whose operator object is empty before calling search: delete filters.k if Object.keys(v).length === 0.
  2. Fix the conditional builder so it does not emit the key when no operator applies.
  3. Validate external filter payloads and strip empty operator objects.

Example fix

// before
const filters = { user_id: {} }; // cond was false

// after
const filters = {};
// or: const filters = cond ? { user_id: { gte: v } } : {};
Defensive patterns

Strategy: validation

Validate before calling

for (const [field, v] of Object.entries(filters)) {
  if (v && typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length === 0) {
    delete filters[field];
  }
}

Type guard

const isNonEmptyOpObject = (v: unknown): v is Record<string, any> =>
  typeof v === 'object' && v !== null && !Array.isArray(v) && Object.keys(v).length > 0;

Prevention

When it happens

Trigger: Passing filters = { user_id: {} } — e.g. spread of an empty variable or optional operators object where no operator was actually set.

Common situations: Building filters conditionally ({ ...(cond ? { gte: v } : {}) }) where cond is false yields {}; API request bodies with 'filters: {field: {}}'; defaults objects merged until empty.

Related errors


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