{"record":{"id":"905281cd53c82baa","repo":"chroma-core/chroma","slug":"k-document-contains-requires-a-string-value","errorCode":null,"errorMessage":"K.DOCUMENT.contains requires a string value","messagePattern":"K\\.DOCUMENT\\.contains requires a string value","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/execution/expression/key.ts","lineNumber":62,"sourceCode":"    const array = iterableToArray(values);\n    assertNonEmptyArray(array, \"$nin requires at least one value\");\n    return createComparisonWhere(this.name, \"$nin\", array);\n  }\n\n  /**\n   * Contains filter.\n   *\n   * On `Key.DOCUMENT`: substring search (value must be a string).\n   * On metadata fields: checks if the array field contains the scalar value.\n   *\n   * @example\n   * K.DOCUMENT.contains(\"machine learning\")   // document substring\n   * K(\"tags\").contains(\"action\")               // metadata array contains\n   * K(\"scores\").contains(42)                   // metadata array contains\n   */\n  public contains(value: string | number | boolean): WhereExpression {\n    if (this.name === \"#document\" && typeof value !== \"string\") {\n      throw new TypeError(\"K.DOCUMENT.contains requires a string value\");\n    }\n    return createComparisonWhere(this.name, \"$contains\", value);\n  }\n\n  /**\n   * Not-contains filter.\n   *\n   * On `Key.DOCUMENT`: excludes documents containing the substring.\n   * On metadata fields: checks that the array field does not contain the scalar value.\n   *\n   * @example\n   * K.DOCUMENT.notContains(\"deprecated\")   // document substring exclusion\n   * K(\"tags\").notContains(\"draft\")          // metadata array not-contains\n   */\n  public notContains(value: string | number | boolean): WhereExpression {\n    if (this.name === \"#document\" && typeof value !== \"string\") {\n      throw new TypeError(\"K.DOCUMENT.notContains requires a string value\");\n    }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/execution/expression/key.ts#L44-L80","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a string when filtering on the document: K.DOCUMENT.contains(\"machine learning\")","In generic filter builders, branch on the key: coerce to string for #document, keep the native type for metadata keys","Fix upstream typing so values destined for document filters are constrained to string"],"exampleFix":"// before\nconst filter = (key: Key, value: string | number | boolean) => key.contains(value);\nfilter(K.DOCUMENT, 42); // TypeError\n\n// after\nconst filter = (key: Key, value: string | number | boolean) =>\n  key.contains(key === K.DOCUMENT ? String(value) : value);","handlingStrategy":"type-guard","validationCode":"const isDocumentContainsValue = (key: Key, value: unknown): boolean =>\n  key !== K.DOCUMENT || typeof value === \"string\";\n\nif (!isDocumentContainsValue(key, value)) {\n  throw new Error(\"Document substring filters require a string value\");\n}\nkey.contains(value as string | number | boolean);","typeGuard":"function containsValueFor(key: Key, value: string | number | boolean): string | number | boolean {\n  return key.name === \"#document\" && typeof value !== \"string\" ? String(value) : value;\n}","tryCatchPattern":null,"preventionTips":["Branch generic filter builders on the #document key and coerce to string","Type filter values as string when the field targets document content","Keep document filters and metadata filters in separate code paths"],"tags":["chroma","where-filter","document","typeerror"],"backgroundTag":"wrong-argument-type","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}