mem0ai/mem0 · error · Error

Oracle filter for field '${metadataKey}' must be a scalar or

Error message

Oracle filter for field '${metadataKey}' must be a scalar or an operator object

What it means

The Oracle filter compiler accepts, per metadata field, either a scalar (equality) or an operator object ({ gte: 1, in: [...] }). A bare array is neither — it cannot become a JSON_EXISTS equality predicate nor an operator map — so it is rejected explicitly rather than guessed at (e.g. silently treated as IN).

Source

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

  value: any,
  binds: Record<string, any>,
): string {
  const path = jsonPath(metadataKey);

  if (value === "*") {
    return `JSON_EXISTS(payload, '$${path}')`;
  }

  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(", ")}`,
    );

View on GitHub (pinned to 001c235229)

Solutions

  1. Wrap arrays in an explicit operator: { tag: { in: ['a','b'] } }.
  2. For equality use a scalar: { user_id: 'alice' }.
  3. If you accept user filters, normalize bare arrays to { in: [...] } before calling the store.

Example fix

// before
filters = { tag: ['a', 'b'] };

// after
filters = { tag: { in: ['a', 'b'] } };
Defensive patterns

Strategy: validation

Validate before calling

for (const [field, v] of Object.entries(filters)) {
  if (Array.isArray(v)) filters[field] = { in: v }; // bare array -> explicit membership
}

Type guard

const isScalarOrOpObject = (v: unknown): boolean =>
  v === null || ['string','number','boolean'].includes(typeof v) ||
  (typeof v === 'object' && v !== null && !Array.isArray(v));

Prevention

When it happens

Trigger: Passing filters = { tag: ['a','b'] } (bare array) to search/list on the Oracle store instead of the operator form { tag: { in: ['a','b'] } }.

Common situations: Filter syntaxes from other backends (Qdrant/mem0 Python) where a bare array implies membership; user-built filters passed straight from an API body; partial migration of filter-building code.

Related errors


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