chroma-core/chroma · error · ChromaValueError
Expected operand for ${operator} to be a list of 'whereDocum
Error message
Expected operand for ${operator} to be a list of 'whereDocument' expressions, but got ${operand} What it means
When the single top-level operator is $and or $or, its operand must be an array of whereDocument expressions (utils.ts:680-685). Passing an object, a string, or any non-array throws this ChromaValueError from validateWhereDocument before a request is sent. Each array element is subsequently validated recursively by the same function.
Source
Thrown at clients/new-js/packages/chromadb/src/utils.ts:682
![
"$contains",
"$not_contains",
"$matches",
"$not_matches",
"$regex",
"$not_regex",
"$and",
"$or",
].includes(operator)
) {
throw new ChromaValueError(
`Expected 'whereDocument' operator to be one of $contains, $not_contains, $matches, $not_matches, $regex, $not_regex, $and, or $or, but got ${operator}`,
);
}
if (operator === "$and" || operator === "$or") {
if (!Array.isArray(operand)) {
throw new ChromaValueError(
`Expected operand for ${operator} to be a list of 'whereDocument' expressions, but got ${operand}`,
);
}
if (operand.length <= 1) {
throw new ChromaValueError(
`Expected 'whereDocument' operand for ${operator} to be a list with at least two 'whereDocument' expressions`,
);
}
operand.forEach((item) => validateWhereDocument(item));
}
if (
(operand === "$contains" ||
operand === "$not_contains" ||
operand === "$regex" ||
operand === "$not_regex") &&View on GitHub (pinned to aecdd12c8a)
Solutions
- Wrap the sub-clauses in an array: { $and: [{ $contains: 'a' }, { $not_contains: 'b' }] }
- Make sure every array element is itself a valid single-operator whereDocument object
- Rely on the WhereDocument type — { $and: WhereDocument[] } is enforced by the compiler
Example fix
// before
whereDocument: { $and: { $contains: 'a' } }
// after
whereDocument: { $and: [{ $contains: 'a' }, { $not_contains: 'b' }] } Defensive patterns
Strategy: validation
Validate before calling
function isCompoundWhereDocument(w: Record<string, unknown>): boolean {
const [op, val] = Object.entries(w)[0];
if (op !== '$and' && op !== '$or') return true; // not compound, nothing to check here
return Array.isArray(val);
}
if (whereDocument && !isCompoundWhereDocument(whereDocument)) {
throw new TypeError('$and/$or require an array of whereDocument clauses');
} Type guard
const isCompoundClause = (w: unknown): w is { $and: unknown[] } | { $or: unknown[] } =>
typeof w === 'object' && w !== null &&
(('$and' in w) || ('$or' in w)) && Array.isArray((w as Record<string, unknown>).$and ?? (w as Record<string, unknown>).$or); Try / catch
try {
await col.query({ queryTexts, whereDocument: { $and: clauses } });
} catch (e) {
if (e instanceof Error && e.message.includes('list of')) {
clauses = [clauses].flat(2); // normalize accidental object/scalar into an array and retry
} else throw e;
} Prevention
- Always build $and/$or operands as arrays: { $and: [ ...clauses ] }
- Add a builder helper (and(clauses) / or(clauses)) that enforces the array shape
- Let the WhereDocument union type reject object-style conjunctions at compile time
When it happens
Trigger: collection.query({ queryTexts: [...], whereDocument: { $and: { $contains: 'a' } } }) (nested object instead of array); { $or: 'text' }; { $and: 123 }.
Common situations: Assuming Mongo-style nested-object conjunctions; adding a second condition and wrapping clauses in braces instead of brackets.
Related errors
- Expected 'whereDocument' operand for ${operator} to be a lis
- Expected 'whereDocument' to have exactly one operator, but g
- Expected 'whereDocument' operator to be one of $contains, $n
- Expected operand for ${operator} to be a non empty string, b
- Expected 'include' to be a non-empty array
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/a5f122234bf18bed.
Report an issue: GitHub.