chroma-core/chroma · error · ChromaValueError
Expected 'where' value for $and or $or to be a list of 'wher
Error message
Expected 'where' value for $and or $or to be a list of 'where' expressions, but got ${value} What it means
When the top-level operator is $and or $or, validateWhere requires its value — an array of where expressions — to have more than one entry; Object.keys on the array yields indices, so length <= 1 throws. A zero- or one-element logical combination is meaningless in Chroma's grammar and is rejected. Each entry is then recursively validated as a full where clause.
Source
Thrown at clients/new-js/packages/chromadb/src/utils.ts:561
);
}
Object.entries(where).forEach(([key, value]) => {
if (
key !== "$and" &&
key !== "$or" &&
key !== "$in" &&
key !== "$nin" &&
!["string", "number", "boolean", "object"].includes(typeof value)
) {
throw new ChromaValueError(
`Expected 'where' value to be a string, number, boolean, or an operator expression, but got ${value}`,
);
}
if (key === "$and" || key === "$or") {
if (Object.keys(value).length <= 1) {
throw new ChromaValueError(
`Expected 'where' value for $and or $or to be a list of 'where' expressions, but got ${value}`,
);
}
value.forEach((w: Where) => validateWhere(w));
return;
}
if (typeof value === "object") {
if (Object.keys(value).length != 1) {
throw new ChromaValueError(
`Expected operator expression to have one operator, but got ${value}`,
);
}
const [operator, operand] = Object.entries(value)[0];
if (View on GitHub (pinned to aecdd12c8a)
Solutions
- Use the single filter directly when the list has one entry: clauses.length === 1 ? clauses[0] : { $and: clauses }.
- Require at least two clauses for $and/$or.
- Always pass an array (not an object) as the $and/$or value.
Example fix
// before
const where = { $and: clauses }; // clauses has 0 or 1 entries
// after
const where = clauses.length > 1 ? { $and: clauses } : clauses[0]; Defensive patterns
Strategy: validation
Validate before calling
const buildLogical = (op, clauses) => {
if (clauses.length > 1) return { [op]: clauses };
if (clauses.length === 1) return clauses[0];
return undefined; // no filters
};
await collection.query({ queryTexts, where: buildLogical('$and', clauses) }); Type guard
const isLogicalWhere = (w: unknown): w is { $and?: object[]; $or?: object[] } =>
typeof w === 'object' && w !== null &&
(Array.isArray((w as any).$and) || Array.isArray((w as any).$or)); Try / catch
try {
await collection.query({ queryTexts, where });
} catch (e) {
if ((e as Error).message.includes('$and or $or')) {
// collapse a single-clause $and/$or to the bare clause and retry
} else {
throw e;
}
} Prevention
- Collapse one-element clause lists to the bare clause before calling.
- Always pass an array as the $and/$or value.
- Skip the query (or omit where) when the clause list is empty.
When it happens
Trigger: where: { $and: [{ genre: 'sci-fi' }] } — single-element $and. where: { $and: [] }. Passing an object instead of an array: { $or: { a: 1 } } (one key).
Common situations: Programmatically building $and from a list of user facets where only one facet was selected; forgetting to fall back to a bare filter when the list has one element.
Related errors
- Expected where to be a non-empty object
- Expected 'where' to have exactly one operator, but got ${Obj
- Expected 'where' value to be a string, number, boolean, or a
- Expected operator expression to have one operator, but got $
- Expected operand value to be a number for ${operator}, but g
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/10acab0ea6a00163.
Report an issue: GitHub.