chroma-core/chroma · error · ChromaValueError

Expected each document to be a string, but got ${typeof docu

Error message

Expected each document to be a string, but got ${typeof document}

What it means

ChromaValueError thrown by validateDocuments (utils.ts:176) per-element when a document entry is falsy and not a string (null/undefined/false/0/NaN) while nullable=false (the default — validateBaseRecordSet never passes nullable=true). Note the guard is `typeof document !== 'string' && !document`, so truthy non-strings (e.g. 42) slip through; this fires for null/undefined holes in the array.

Source

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

  documents: (string | null | undefined)[];
  fieldName: string;
  nullable?: boolean;
}) => {
  if (!Array.isArray(documents)) {
    throw new ChromaValueError(
      `Expected '${fieldName}' to be an array, but got ${typeof documents}`,
    );
  }

  if (documents.length === 0) {
    throw new ChromaValueError(
      `Expected '${fieldName}' to be a non-empty list`,
    );
  }

  documents.forEach((document) => {
    if (!nullable && typeof document !== "string" && !document) {
      throw new ChromaValueError(
        `Expected each document to be a string, but got ${typeof document}`,
      );
    }
  });
};

/**
 * Validates an array of IDs for type correctness and uniqueness.
 * @param ids - Array of ID strings to validate
 * @throws ChromaValueError if IDs are not strings, empty, or contain duplicates
 */
export const validateIDs = (ids: string[]) => {
  if (!Array.isArray(ids)) {
    throw new ChromaValueError(
      `Expected 'ids' to be an array, but got ${typeof ids}`,
    );
  }

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Coalesce holes to a string: documents.map(d => d ?? '')
  2. Filter out rows without text and add them in a separate batch (or with embeddings only)
  3. If nulls are intentional, note this client validator does not expose nullable=true on the public path — avoid nulls in documents

Example fix

// before
await collection.add({ ids, documents: [doc1, null, doc3] });
// after
await collection.add({ ids, documents: [doc1, doc2 ?? "", doc3] });
Defensive patterns

Strategy: type-guard

Validate before calling

const bad = documents.findIndex(d => d !== null && d !== undefined && typeof d !== 'string');
if (bad !== -1) throw new TypeError(`documents[${bad}] is not a string`);
if (documents.some(d => d == null)) documents = documents.map(d => d ?? '');

Type guard

function isDocumentArray(v): v is string[] { return Array.isArray(v) && v.every(d => typeof d === 'string'); }

Try / catch

try { await collection.add({ ids, documents }); } catch (e) { if (e instanceof ChromaValueError && /each document to be a string/.test(e.message)) documents = documents.map(d => d ?? ''); else throw e; }

Prevention

When it happens

Trigger: collection.add({ ids, documents: ['a', null, 'c'] }) with default nullable=false; sparse rows mapped as documents: rows.map(r => r.text) where r.text is undefined; update({ ids, documents }) with null placeholders.

Common situations: Optional text columns where some rows lack a body; JSON ingestion producing nulls; mixing documents and embeddings where some records intentionally have no text (currently not allowed by this validator).

Related errors


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