chroma-core/chroma · error · ChromaValueError

Expected metadatas to be an array, but got ${typeof metadata

Error message

Expected metadatas to be an array, but got ${typeof metadatas}

What it means

validateMetadatas, invoked from validateBaseRecordSet during add/upsert, requires the metadatas argument to be an array (one metadata object or null per record, aligned with ids). Passing an object, a string, or any non-array raises ChromaValueError client-side. TypeScript types usually prevent this; untyped JavaScript or deserialized payloads can trigger it.

Source

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

  }

  if (metadatas === null) {
    return null;
  }

  return metadatas.map((metadataArray) => {
    if (metadataArray === null) {
      return null;
    }

    const deserialized = deserializeMetadatas(metadataArray);
    return deserialized ?? [];
  });
};

const validateMetadatas = (metadatas: Metadata[]) => {
  if (!Array.isArray(metadatas)) {
    throw new ChromaValueError(
      `Expected metadatas to be an array, but got ${typeof metadatas}`,
    );
  }

  metadatas.forEach((metadata) => validateMetadata(metadata));
};

/**
 * Validates a base record set for required fields and data consistency.
 * @param options - Validation options
 * @param options.recordSet - The record set to validate
 * @param options.update - Whether this is for an update operation (relaxes requirements)
 * @param options.embeddingsField - Name of the embeddings field for error messages
 * @param options.documentsField - Name of the documents field for error messages
 * @throws ChromaValueError if validation fails
 */
export const validateBaseRecordSet = ({
  recordSet,

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Wrap per-record metadata in an array with one entry per id: metadatas: [{ genre: 'sci-fi' }].
  2. Check Array.isArray(metadatas) before calling add()/upsert() when input comes from external data.
  3. Keep metadatas, documents, and ids the same length.

Example fix

// before
await collection.add({ ids: ['1'], documents: ['d'], metadatas: { genre: 'sci-fi' } });

// after
await collection.add({ ids: ['1'], documents: ['d'], metadatas: [{ genre: 'sci-fi' }] });
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(metadatas)) {
  throw new TypeError('metadatas must be an array with one entry per id');
}
await collection.add({ ids, metadatas });

Type guard

const isMetadataArray = (v: unknown): v is unknown[] => Array.isArray(v);

Try / catch

try {
  await collection.add({ ids, metadatas });
} catch (e) {
  if ((e as Error).message.includes('metadatas to be an array')) {
    await collection.add({ ids, metadatas: [metadatas] }); // wrap single object
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: collection.add({ metadatas: { genre: 'sci-fi' } }) — single object instead of an array. metadatas: JSON.parse(raw) where the payload is an object. metadatas: 'none'.

Common situations: Copying a single-record example into a batched call without wrapping in an array; passing deserialized JSON whose shape differs from the typed contract; JS callers bypassing TypeScript checks.

Related errors


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