chroma-core/chroma · error · ChromaValueError

Expected operator to be one of $gt, $gte, $lt, $lte, $ne, $e

Error message

Expected operator to be one of $gt, $gte, $lt, $lte, $ne, $eq, $in, $nin, $contains, $not_contains, but got ${operator}

What it means

The operator whitelist in validateWhere is $gt, $gte, $lt, $lte, $ne, $eq, $in, $nin, $contains, $not_contains; anything else in an operator expression throws ChromaValueError. There is no $regex, $like, $between, or $exists in Chroma's where grammar. Operators are lowercase — case variants like $Gt also fail.

Source

Thrown at clients/new-js/packages/chromadb/src/utils.ts:617

          `Expected operand value to be a string, number, or boolean for ${operator}, but got ${typeof operand}`,
        );
      }

      if (
        ![
          "$gt",
          "$gte",
          "$lt",
          "$lte",
          "$ne",
          "$eq",
          "$in",
          "$nin",
          "$contains",
          "$not_contains",
        ].includes(operator)
      ) {
        throw new ChromaValueError(
          `Expected operator to be one of $gt, $gte, $lt, $lte, $ne, $eq, $in, $nin, $contains, $not_contains, but got ${operator}`,
        );
      }

      if (
        !["string", "number", "boolean"].includes(typeof operand) &&
        !Array.isArray(operand)
      ) {
        throw new ChromaValueError(
          "Expected operand value to be a string, number, boolean, or a list of those types",
        );
      }

      if (
        Array.isArray(operand) &&
        (operand.length === 0 ||
          !operand.every((item) => typeof item === typeof operand[0]))
      ) {

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Replace $regex/$like with $contains (substring) or $not_contains.
  2. Express $between as an $and of $gte/$lte clauses.
  3. Check operator names against the exact lowercase whitelist.

Example fix

// before
where: { name: { $like: '%Ada%' } }

// after
where: { name: { $contains: 'Ada' } }
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = new Set(['$gt','$gte','$lt','$lte','$ne','$eq','$in','$nin','$contains','$not_contains']);
const assertOperators = (w) => {
  for (const v of Object.values(w)) {
    if (typeof v === 'object' && v !== null && !Array.isArray(v)) {
      for (const op of Object.keys(v)) {
        if (!ALLOWED.has(op)) throw new Error(`Unsupported operator: ${op}`);
      }
    }
  }
};

Type guard

const isAllowedOperator = (op: string): op is
  '$gt'|'$gte'|'$lt'|'$lte'|'$ne'|'$eq'|'$in'|'$nin'|'$contains'|'$not_contains' =>
  ['$gt','$gte','$lt','$lte','$ne','$eq','$in','$nin','$contains','$not_contains'].includes(op);

Try / catch

try {
  await collection.query({ queryTexts, where });
} catch (e) {
  if ((e as Error).message.includes('Expected operator to be one of')) {
    // replace $regex/$like with $contains, $between with $gte/$lte, then retry
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: where: { name: { $regex: '^A' } }. { value: { $between: [1, 5] } }. { count: { $Gt: 10 } } (wrong case). { field: { $exists: true } }.

Common situations: Porting Mongo or SQL filters wholesale; IDE autocompletion suggesting Mongo operators; assuming SQL LIKE maps to a $like operator.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/b0dec76b8f11bff5. Report an issue: GitHub.