chroma-core/chroma · error · TypeError

K.DOCUMENT.contains requires a string value

Error message

K.DOCUMENT.contains requires a string value

What it means

K.DOCUMENT is the '#document' pseudo-key for filtering on document content. Its contains() operator performs substring search, which only makes sense on strings, so passing a number or boolean with K.DOCUMENT.contains() raises a TypeError. Metadata-field keys (e.g. K("tags")) accept string|number|boolean for array-contains semantics — the restriction is specific to #document.

Source

Thrown at clients/new-js/packages/chromadb/src/execution/expression/key.ts:62

    const array = iterableToArray(values);
    assertNonEmptyArray(array, "$nin requires at least one value");
    return createComparisonWhere(this.name, "$nin", array);
  }

  /**
   * Contains filter.
   *
   * On `Key.DOCUMENT`: substring search (value must be a string).
   * On metadata fields: checks if the array field contains the scalar value.
   *
   * @example
   * K.DOCUMENT.contains("machine learning")   // document substring
   * K("tags").contains("action")               // metadata array contains
   * K("scores").contains(42)                   // metadata array contains
   */
  public contains(value: string | number | boolean): WhereExpression {
    if (this.name === "#document" && typeof value !== "string") {
      throw new TypeError("K.DOCUMENT.contains requires a string value");
    }
    return createComparisonWhere(this.name, "$contains", value);
  }

  /**
   * Not-contains filter.
   *
   * On `Key.DOCUMENT`: excludes documents containing the substring.
   * On metadata fields: checks that the array field does not contain the scalar value.
   *
   * @example
   * K.DOCUMENT.notContains("deprecated")   // document substring exclusion
   * K("tags").notContains("draft")          // metadata array not-contains
   */
  public notContains(value: string | number | boolean): WhereExpression {
    if (this.name === "#document" && typeof value !== "string") {
      throw new TypeError("K.DOCUMENT.notContains requires a string value");
    }

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Pass a string when filtering on the document: K.DOCUMENT.contains("machine learning")
  2. In generic filter builders, branch on the key: coerce to string for #document, keep the native type for metadata keys
  3. Fix upstream typing so values destined for document filters are constrained to string

Example fix

// before
const filter = (key: Key, value: string | number | boolean) => key.contains(value);
filter(K.DOCUMENT, 42); // TypeError

// after
const filter = (key: Key, value: string | number | boolean) =>
  key.contains(key === K.DOCUMENT ? String(value) : value);
Defensive patterns

Strategy: type-guard

Validate before calling

const isDocumentContainsValue = (key: Key, value: unknown): boolean =>
  key !== K.DOCUMENT || typeof value === "string";

if (!isDocumentContainsValue(key, value)) {
  throw new Error("Document substring filters require a string value");
}
key.contains(value as string | number | boolean);

Type guard

function containsValueFor(key: Key, value: string | number | boolean): string | number | boolean {
  return key.name === "#document" && typeof value !== "string" ? String(value) : value;
}

Prevention

When it happens

Trigger: K.DOCUMENT.contains(42) or K.DOCUMENT.contains(true). Typically a generic filter builder that forwards the same user-supplied value to whichever key the user picked, including #document.

Common situations: A UI or API layer where users choose a field and a value; when the field is the document body and the value is numeric, the call fails. TypeScript users hit it through any-typed values or casts that bypass the declared union; JavaScript users hit it directly.

Related errors


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