chroma-core/chroma · error · ChromaValueError
Expected operand value to be a number for ${operator}, but g
Error message
Expected operand value to be a number for ${operator}, but got ${typeof operand} What it means
Comparison operators $gt, $gte, $lt, $lte accept only numeric operands; validateWhere throws when the operand's typeof is not number. String digits like { $gte: '10' } are rejected even though they look numeric, because Chroma compares typed metadata. Use a real number or convert with Number().
Source
Thrown at clients/new-js/packages/chromadb/src/utils.ts:583
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 (
["$gt", "$gte", "$lt", "$lte"].includes(operator) &&
typeof operand !== "number"
) {
throw new ChromaValueError(
`Expected operand value to be a number for ${operator}, but got ${typeof operand}`,
);
}
if (["$in", "$nin"].includes(operator) && !Array.isArray(operand)) {
throw new ChromaValueError(
`Expected operand value to be an array for ${operator}, but got ${operand}`,
);
}
if (
["$contains", "$not_contains"].includes(operator) &&
!["string", "number", "boolean"].includes(typeof operand)
) {
throw new ChromaValueError(
`Expected operand value to be a string, number, or boolean for ${operator}, but got ${typeof operand}`,
);
}View on GitHub (pinned to aecdd12c8a)
Solutions
- Convert operands: { $gte: Number(req.query.year) }.
- Store the filtered field as numeric metadata at ingestion time.
- For string matching use $eq/$contains instead of ordering operators.
Example fix
// before
where: { year: { $gte: req.query.year } } // '2020' string
// after
where: { year: { $gte: Number(req.query.year) } } Defensive patterns
Strategy: validation
Validate before calling
const numeric = (v) => typeof v === 'number' ? v : Number(v);
await collection.query({ queryTexts, where: { year: { $gte: numeric(req.query.year) } } }); Type guard
const isNumericOperand = (v: unknown, op: string): v is number => !['$gt', '$gte', '$lt', '$lte'].includes(op) || typeof v === 'number';
Try / catch
try {
await collection.query({ queryTexts, where });
} catch (e) {
if ((e as Error).message.includes('to be a number for')) {
// coerce the operand with Number() and retry
} else {
throw e;
}
} Prevention
- Convert query-param strings to numbers before building filters.
- Store numeric-filter fields as numbers in metadata at ingestion.
- Do not use $gt/$lt on string fields — Chroma only supports numeric comparisons.
When it happens
Trigger: where: { year: { $gte: '2020' } } — value taken from a URL/query param (always a string). { $lt: '1700000000' }. Attempting lexicographic string comparison: { name: { $gt: 'A' } }.
Common situations: HTTP query parameters arriving as strings; CSV/JSON ingestion leaving numbers as strings; trying to order strings with comparison operators (unsupported).
Related errors
- Expected 'where' value to be a string, number, boolean, or a
- Expected ids to be strings, found ${typeof ids[i]} at index
- Expected metadata list value for key '${key}' to contain onl
- Expected metadata list value for key '${key}' to contain onl
- Expected metadata value for key '${key}' to be a string, num
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/35be7c89fa249ffa.
Report an issue: GitHub.