chroma-core/chroma · error · Error
Unsupported where operator: ${operator}
Error message
Unsupported where operator: ${operator} What it means
The parser resolves each operator key against a fixed map that supports exactly: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains, $not_contains, $regex and $not_regex. Any other operator string inside an operator dictionary throws this error client-side. Notably there is no $between, $like, $exists or $size.
Source
Thrown at clients/new-js/packages/chromadb/src/execution/expression/where.ts:231
throw new Error("Where dictionary must contain exactly one field");
}
const [field, value] = entries[0];
if (!isPlainObject(value)) {
return new ComparisonWhere(field, "$eq", value);
}
const operatorEntries = Object.entries(value);
if (operatorEntries.length !== 1) {
throw new Error(
`Operator dictionary for field "${field}" must contain exactly one operator`,
);
}
const [operator, operand] = operatorEntries[0];
const factory = comparisonOperatorMap.get(operator);
if (!factory) {
throw new Error(`Unsupported where operator: ${operator}`);
}
return factory(field, operand);
};
export const createComparisonWhere = (
key: string,
operator: string,
value: unknown,
): WhereExpression => new ComparisonWhere(key, operator, value);
View on GitHub (pinned to aecdd12c8a)
Solutions
- Replace $between with { $and: [{ f: { $gte: min } }, { f: { $lte: max } }] }.
- Replace $like with $contains (substring) or $regex (pattern).
- Drop $exists — model optional metadata explicitly or filter client-side.
- Check spelling and case against the supported list: $eq $ne $gt $gte $lt $lte $in $nin $contains $not_contains $regex $not_regex.
Example fix
// before
where: { title: { $like: 'report' } }
// after
where: { title: { $contains: 'report' } } Defensive patterns
Strategy: type-guard
Validate before calling
const SUPPORTED_OPERATORS = new Set([
'$eq', '$ne', '$gt', '$gte', '$lt', '$lte',
'$in', '$nin', '$contains', '$not_contains', '$regex', '$not_regex',
]);
function assertSupportedOperators(where: Record<string, unknown>): void {
for (const [k, v] of Object.entries(where)) {
if (k === '$and' || k === '$or') {
(v as unknown[]).forEach((c) => assertSupportedOperators(c as Record<string, unknown>));
continue;
}
if (v && typeof v === 'object' && !Array.isArray(v)) {
for (const op of Object.keys(v)) {
if (!SUPPORTED_OPERATORS.has(op)) {
throw new Error(`Unsupported operator ${op} on field ${k}`);
}
}
}
}
} Type guard
function isSupportedOperator(op: string): boolean {
return [
'$eq', '$ne', '$gt', '$gte', '$lt', '$lte',
'$in', '$nin', '$contains', '$not_contains', '$regex', '$not_regex',
].includes(op);
} Try / catch
try {
await collection.query({ where });
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unsupported where operator')) {
// rewrite the clause ($between -> $and range, $like -> $contains) and retry
} else {
throw e;
}
} Prevention
- Centralize the operator list in one constant mirrored from comparisonOperatorMap and reuse it everywhere.
- Unit-test every operator your app emits through the where parser.
- When upgrading the chromadb client, diff the supported operator list before adopting new syntax.
When it happens
Trigger: where: { price: { $between: [10, 100] } }; Mongo-isms like { title: { $like: '%report%' } } or { tags: { $exists: true } }; casing or spelling typos like $GTE, $greter, $Contain.
Common situations: Translating MongoDB or SQL WHERE syntax to Chroma; using an operator added in a newer Chroma server version that this client's parser does not know; hand-typing operator strings without a shared constant.
Related errors
- $or must be a non-empty array
- Where dictionary must contain exactly one field
- Operator dictionary for field "${field}" must contain exactl
- K.DOCUMENT.contains requires a string value
- K.DOCUMENT.notContains requires a string value
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/5c2b7da9bd95647d.
Report an issue: GitHub.