chroma-core/chroma · error · ChromaValueError

Expected 'whereDocument' to be a non-empty object

Error message

Expected 'whereDocument' to be a non-empty object

What it means

validateWhereDocument is the whereDocument counterpart of the where type gate: a non-object value (string, number, etc.) throws ChromaValueError. whereDocument must be an object with exactly one operator (e.g. $contains) whose operand is a string. Passing raw search text directly is the classic mistake.

Source

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

        (operand.length === 0 ||
          !operand.every((item) => typeof item === typeof operand[0]))
      ) {
        throw new ChromaValueError(
          "Expected 'where' operand value to be a non-empty list and all values to be of the same type",
        );
      }
    }
  });
};

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

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

  const [operator, operand] = Object.entries(whereDocument)[0];
  if (
    ![
      "$contains",
      "$not_contains",
      "$matches",
      "$not_matches",
      "$regex",

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Wrap text in an operator: whereDocument: { $contains: 'machine learning' }.
  2. Parse JSON strings before passing them.
  3. Use queryTexts or queryEmbeddings for semantic search — whereDocument is only for content filtering.

Example fix

// before
await collection.query({ queryTexts: ['ai'], whereDocument: 'machine learning' });

// after
await collection.query({ queryTexts: ['ai'], whereDocument: { $contains: 'machine learning' } });
Defensive patterns

Strategy: type-guard

Validate before calling

if (whereDocument !== undefined && (typeof whereDocument !== 'object' || whereDocument === null)) {
  throw new TypeError('whereDocument must be like { $contains: \'text\' }');
}
await collection.query({ queryTexts, whereDocument });

Type guard

const isWhereDocument = (w: unknown): w is { $contains?: string; $not_contains?: string } =>
  typeof w === 'object' && w !== null && !Array.isArray(w);

Try / catch

try {
  await collection.query({ queryTexts, whereDocument });
} catch (e) {
  if ((e as Error).message.includes('whereDocument')) {
    // wrap the raw text as { $contains: text } and retry
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: collection.query({ whereDocument: 'machine learning' }) — raw string. whereDocument: 42. A JSON string that was never parsed.

Common situations: Assuming whereDocument takes search text directly; wiring a search box input straight into the option; confusing content filtering (whereDocument) with semantic search (queryTexts).

Related errors


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