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
- Coalesce holes to a string: documents.map(d => d ?? '')
- Filter out rows without text and add them in a separate batch (or with embeddings only)
- 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
- Coalesce null/undefined text to '' before insert
- Filter textless rows into a separate embeddings-only batch
- Validate parsed JSON payloads for null text fields
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
- Expected '${fieldName}' to be an array, but got ${typeof doc
- Expected '${fieldName}' to be a non-empty list
- At least one of ${recordSetFields.join(", ")} must be provid
- Non-empty lists are required for ${zeroLength.join(", ")}
- Unequal lengths for fields ${lengths.map(([field, _]) => fie
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/1ffdca0197f3cf73.
Report an issue: GitHub.