{"record":{"id":"10acab0ea6a00163","repo":"chroma-core/chroma","slug":"expected-where-value-for-and-or-or-to-be-a-lis","errorCode":null,"errorMessage":"Expected 'where' value for $and or $or to be a list of 'where' expressions, but got ${value}","messagePattern":"Expected 'where' value for \\$and or \\$or to be a list of 'where' expressions, but got (.+?)","errorType":"validation","errorClass":"ChromaValueError","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/utils.ts","lineNumber":561,"sourceCode":"    );\n  }\n\n  Object.entries(where).forEach(([key, value]) => {\n    if (\n      key !== \"$and\" &&\n      key !== \"$or\" &&\n      key !== \"$in\" &&\n      key !== \"$nin\" &&\n      ![\"string\", \"number\", \"boolean\", \"object\"].includes(typeof value)\n    ) {\n      throw new ChromaValueError(\n        `Expected 'where' value to be a string, number, boolean, or an operator expression, but got ${value}`,\n      );\n    }\n\n    if (key === \"$and\" || key === \"$or\") {\n      if (Object.keys(value).length <= 1) {\n        throw new ChromaValueError(\n          `Expected 'where' value for $and or $or to be a list of 'where' expressions, but got ${value}`,\n        );\n      }\n\n      value.forEach((w: Where) => validateWhere(w));\n      return;\n    }\n\n    if (typeof value === \"object\") {\n      if (Object.keys(value).length != 1) {\n        throw new ChromaValueError(\n          `Expected operator expression to have one operator, but got ${value}`,\n        );\n      }\n\n      const [operator, operand] = Object.entries(value)[0];\n\n      if (","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/utils.ts#L543-L579","documentation":"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.","triggerScenarios":"where: { $and: [{ genre: 'sci-fi' }] } — single-element $and. where: { $and: [] }. Passing an object instead of an array: { $or: { a: 1 } } (one key).","commonSituations":"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.","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."],"exampleFix":"// before\nconst where = { $and: clauses }; // clauses has 0 or 1 entries\n\n// after\nconst where = clauses.length > 1 ? { $and: clauses } : clauses[0];","handlingStrategy":"validation","validationCode":"const buildLogical = (op, clauses) => {\n  if (clauses.length > 1) return { [op]: clauses };\n  if (clauses.length === 1) return clauses[0];\n  return undefined; // no filters\n};\nawait collection.query({ queryTexts, where: buildLogical('$and', clauses) });","typeGuard":"const isLogicalWhere = (w: unknown): w is { $and?: object[]; $or?: object[] } =>\n  typeof w === 'object' && w !== null &&\n  (Array.isArray((w as any).$and) || Array.isArray((w as any).$or));","tryCatchPattern":"try {\n  await collection.query({ queryTexts, where });\n} catch (e) {\n  if ((e as Error).message.includes('$and or $or')) {\n    // collapse a single-clause $and/$or to the bare clause and retry\n  } else {\n    throw e;\n  }\n}","preventionTips":["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."],"tags":["where-filter","validation","logical-operators"],"backgroundTag":"invalid-where-clause","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}