{"record":{"id":"f996e4fce60b5b31","repo":"chroma-core/chroma","slug":"expected-wheredocument-operator-to-be-one-of-co","errorCode":null,"errorMessage":"Expected 'whereDocument' operator to be one of $contains, $not_contains, $matches, $not_matches, $regex, $not_regex, $and, or $or, but got ${operator}","messagePattern":"Expected 'whereDocument' operator to be one of \\$contains, \\$not_contains, \\$matches, \\$not_matches, \\$regex, \\$not_regex, \\$and, or \\$or, but got (.+?)","errorType":"validation","errorClass":"ChromaValueError","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/utils.ts","lineNumber":675,"sourceCode":"    throw new ChromaValueError(\n      `Expected 'whereDocument' to have exactly one operator, but got ${whereDocument}`,\n    );\n  }\n\n  const [operator, operand] = Object.entries(whereDocument)[0];\n  if (\n    ![\n      \"$contains\",\n      \"$not_contains\",\n      \"$matches\",\n      \"$not_matches\",\n      \"$regex\",\n      \"$not_regex\",\n      \"$and\",\n      \"$or\",\n    ].includes(operator)\n  ) {\n    throw new ChromaValueError(\n      `Expected 'whereDocument' operator to be one of $contains, $not_contains, $matches, $not_matches, $regex, $not_regex, $and, or $or, but got ${operator}`,\n    );\n  }\n\n  if (operator === \"$and\" || operator === \"$or\") {\n    if (!Array.isArray(operand)) {\n      throw new ChromaValueError(\n        `Expected operand for ${operator} to be a list of 'whereDocument' expressions, but got ${operand}`,\n      );\n    }\n\n    if (operand.length <= 1) {\n      throw new ChromaValueError(\n        `Expected 'whereDocument' operand for ${operator} to be a list with at least two 'whereDocument' expressions`,\n      );\n    }\n\n    operand.forEach((item) => validateWhereDocument(item));","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/utils.ts#L657-L693","documentation":"validateWhereDocument accepts only eight operators as the single top-level key: $contains, $not_contains, $matches, $not_matches, $regex, $not_regex, $and, $or (utils.ts:663-678). Any other key — metadata-where operators like $eq/$gt/$ne, un-prefixed names, or typos — throws this ChromaValueError client-side before a request is made. Document filters are text-matching operators; field-based operators belong to the separate `where` clause.","triggerScenarios":"collection.get({ whereDocument: { $eq: 'text' } }); whereDocument: { contains: 'x' } (missing $); { $matchs: 'x' } (typo); reusing a metadata `where` clause object as whereDocument in get/query/delete.","commonSituations":"Copy-pasting from `where` filter examples (those use $eq/$ne/$gt/$lte/$in/$nin); assuming Mongo-style operator syntax; older Chroma docs that only documented $contains.","solutions":["Use one of the eight documented document operators; for exact-text matching use { $regex: '^exact$' } instead of $eq","Use the `where` parameter (not whereDocument) when filtering on metadata fields and values","Check the exported WhereDocument type — the compiler enumerates the legal keys"],"exampleFix":"// before\nawait col.get({ whereDocument: { $eq: 'hello' } });\n\n// after\nawait col.get({ whereDocument: { $regex: '^hello$' } });","handlingStrategy":"validation","validationCode":"const DOC_OPERATORS = ['$contains', '$not_contains', '$matches', '$not_matches', '$regex', '$not_regex', '$and', '$or'];\nconst op = whereDocument && Object.keys(whereDocument)[0];\nif (op !== undefined && !DOC_OPERATORS.includes(op)) {\n  throw new Error(`unsupported whereDocument operator: ${op}; use one of ${DOC_OPERATORS.join(', ')}`);\n}","typeGuard":"const DOC_OPS = ['$contains', '$not_contains', '$matches', '$not_matches', '$regex', '$not_regex', '$and', '$or'];\nconst hasDocumentOperator = (w: unknown): w is { [k: string]: unknown } =>\n  typeof w === 'object' && w !== null && DOC_OPS.includes(Object.keys(w)[0]);","tryCatchPattern":"try {\n  await col.get({ whereDocument });\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"whereDocument' operator to be one of\")) {\n    // map the bad operator to a legal one (e.g. $eq -> { $regex: `^${value}$` })\n  } else throw e;\n}","preventionTips":["Keep a shared constant of the eight legal document operators and assert against it","Keep metadata filters in `where` and text filters in `whereDocument` — never share clause objects between them","Enable strict TypeScript on filter-building code so invalid keys surface at compile time"],"tags":["javascript","typescript","validation","where-document","operators"],"backgroundTag":"invalid-query-filter","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}