chroma-core/chroma · error · TypeError

K.DOCUMENT.notContains requires a string value

Error message

K.DOCUMENT.notContains requires a string value

What it means

K.DOCUMENT.notContains() excludes documents whose text contains a substring, so the value must be a string. Passing a number or boolean with K.DOCUMENT.notContains() raises a TypeError client-side, before any request is sent. Metadata-field keys accept string|number|boolean; the restriction applies only to the '#document' pseudo-key.

Source

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

    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");
    }
    return createComparisonWhere(this.name, "$not_contains", value);
  }

  public regex(pattern: string): WhereExpression {
    if (typeof pattern !== "string") {
      throw new TypeError("$regex requires a string pattern");
    }
    return createComparisonWhere(this.name, "$regex", pattern);
  }

  public notRegex(pattern: string): WhereExpression {
    if (typeof pattern !== "string") {
      throw new TypeError("$not_regex requires a string pattern");
    }
    return createComparisonWhere(this.name, "$not_regex", pattern);
  }
}

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Pass a string: K.DOCUMENT.notContains("deprecated")
  2. In shared filter code, convert values with String(value) when the target key is #document
  3. Skip document-text exclusion entirely when the value is not a meaningful string

Example fix

// before
K.DOCUMENT.notContains(excludeId); // excludeId = 0 -> TypeError

// after
typeof excludeId === "string"
  ? K.DOCUMENT.notContains(excludeId)
  : K("owner_id").notContains(excludeId);
Defensive patterns

Strategy: type-guard

Validate before calling

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

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

Type guard

function notContainsValueFor(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.notContains(0) or K.DOCUMENT.notContains(false). Common in generic exclusion filters that reuse one value across document and metadata keys.

Common situations: Building an exclusion list where some entries are numbers (IDs) and code forwards them verbatim to K.DOCUMENT. Passing falsy sentinels (0, false) intending 'exclude nothing'.

Related errors


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