chroma-core/chroma · error · ChromaValueError

Expected where to be a non-empty object

Error message

Expected where to be a non-empty object

What it means

validateWhere rejects a where argument whose typeof is not 'object'. This is a type gate: strings, numbers, booleans, and other non-object filters throw ChromaValueError immediately, client-side. Subsequent checks require exactly one top-level key, so the where clause must be a single-key operator object.

Source

Thrown at clients/new-js/packages/chromadb/src/utils.ts:535

export const validateMaxBatchSize = (
  recordSetLength: number,
  maxBatchSize: number,
) => {
  if (recordSetLength > maxBatchSize) {
    throw new ChromaValueError(
      `Record set length ${recordSetLength} exceeds max batch size ${maxBatchSize}`,
    );
  }
};

/**
 * Validates a where clause for metadata filtering.
 * @param where - Where clause object to validate
 * @throws ChromaValueError if the where clause is malformed
 */
export const validateWhere = (where: Where) => {
  if (typeof where !== "object") {
    throw new ChromaValueError("Expected where to be a non-empty object");
  }

  if (Object.keys(where).length != 1) {
    throw new ChromaValueError(
      `Expected 'where' to have exactly one operator, but got ${
        Object.keys(where).length
      }`,
    );
  }

  Object.entries(where).forEach(([key, value]) => {
    if (
      key !== "$and" &&
      key !== "$or" &&
      key !== "$in" &&
      key !== "$nin" &&
      !["string", "number", "boolean", "object"].includes(typeof value)
    ) {

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Pass a structured object: where: { genre: 'sci-fi' } or where: { $and: [ ... ] }.
  2. Parse JSON strings before use: where: JSON.parse(raw).
  3. Omit the where option entirely when no filtering is needed — do not pass a primitive placeholder.

Example fix

// before
await collection.query({ queryTexts: ['x'], where: 'genre = sci-fi' });

// after
await collection.query({ queryTexts: ['x'], where: { genre: 'sci-fi' } });
Defensive patterns

Strategy: type-guard

Validate before calling

if (where !== undefined && (typeof where !== 'object' || where === null)) {
  throw new TypeError('where must be an object like { field: value } or { $and: [...] }');
}
await collection.query({ queryTexts, where });

Type guard

const isWhere = (w: unknown): w is Record<string, unknown> =>
  typeof w === 'object' && w !== null && !Array.isArray(w);

Try / catch

try {
  await collection.query({ queryTexts, where });
} catch (e) {
  if ((e as Error).message.includes('where to be a non-empty object')) {
    // fix the where shape to an object, or omit it and retry
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: collection.query({ where: 'genre = sci-fi' }) — passing a raw SQL-ish string. where: 123. Spreading a string variable into the where option by mistake.

Common situations: Translating SQL or Mongo-like filter strings into Chroma's structured filters; a filter builder returning a primitive when no criteria exist; passing a serialized JSON string instead of a parsed object.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/1f5fd49cc019e178. Report an issue: GitHub.