chroma-core/chroma · error

ids, embeddings, metadatas, and documents must all be the sa

Error message

ids, embeddings, metadatas, and documents must all be the same length

What it means

prepareRecordRequest() cross-checks that ids, embeddings (as supplied or as generated from documents), metadatas, and documents all have the same length; any mismatch throws before the request is sent. This guards the server from pairing record i's id with record j's vector. Note it checks array lengths only — per-vector dimensionality is validated server-side.

Source

Thrown at clients/js/packages/chromadb-core/src/utils.ts:143

  if (!embeddingsArray && !update) {
    throw new Error("Failed to generate embeddings for your request.");
  }

  for (let i = 0; i < ids.length; i += 1) {
    if (typeof ids[i] !== "string") {
      throw new Error(
        `Expected ids to be strings, found ${typeof ids[i]} at index ${i}`,
      );
    }
  }

  if (
    (embeddingsArray !== undefined && ids.length !== embeddingsArray.length) ||
    (metadatas !== undefined && ids.length !== metadatas.length) ||
    (documents !== undefined && ids.length !== documents.length)
  ) {
    throw new Error(
      "ids, embeddings, metadatas, and documents must all be the same length",
    );
  }

  const uniqueIds = new Set(ids);
  if (uniqueIds.size !== ids.length) {
    const duplicateIds = ids.filter(
      (item, index) => ids.indexOf(item) !== index,
    );
    throw new Error(
      `ID's must be unique, found duplicates for: ${duplicateIds}`,
    );
  }

  if (
    embeddingsArray &&
    embeddingsArray.some((embedding) => embedding.length === 0)
  ) {

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Assert equal lengths before add: if (ids.length !== documents.length) throw new Error(...) with batch context.
  2. When using precomputed embeddings, compute them from the exact documents array passed in this call.
  3. Rebuild all arrays from a single source-of-truth list of records ({ id, document, metadata }) so they cannot diverge.
  4. After any filter/map/slice on one array, apply the identical transformation to the others.

Example fix

// before
await collection.add({
  ids, // 10 ids
  documents, // 10 documents
  metadatas: metadatas.slice(0, 8), // stale slice -> length mismatch
});

// after
const batch = records.slice(offset, offset + size); // single source of truth
await collection.add({
  ids: batch.map((r) => r.id),
  documents: batch.map((r) => r.text),
  metadatas: batch.map((r) => r.meta),
});
Defensive patterns

Strategy: validation

Validate before calling

function assertEqualLengths(p: {
  ids: string[];
  embeddings?: number[][];
  metadatas?: Record<string, unknown>[];
  documents?: string[];
}) {
  const n = p.ids.length;
  const parts: [string, number | undefined][] = [
    ["embeddings", p.embeddings?.length],
    ["metadatas", p.metadatas?.length],
    ["documents", p.documents?.length],
  ];
  const bad = parts.filter(([, len]) => len !== undefined && len !== n);
  if (bad.length) throw new Error(`Length mismatch vs ids(${n}): ${bad.map(([k, l]) => `${k}(${l})`).join(", ")}`);
}
assertEqualLengths(params);
await collection.add(params);

Prevention

When it happens

Trigger: collection.add({ ids, documents, metadatas }) where metadatas was built for a different chunking/batch than documents; passing precomputed embeddings computed from a different text array; slicing one array during batching but not the others; a retry path that reuses ids but rebuilds documents with a filter.

Common situations: Chunked ingestion pipelines where embeddings are cached from a previous chunking run; off-by-one in batch slicing; mapping/filtering one array (documents.filter(...)) while keeping ids and metadatas unfiltered.

Related errors


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