chroma-core/chroma · error · ChromaValueError

Expected metadata list value for key '${key}' to contain onl

Error message

Expected metadata list value for key '${key}' to contain only the same type, got mixed types

What it means

validateMetadataListValue records typeof of the first array element and throws when any later element differs. Chroma metadata lists must be homogeneous: all strings, all numbers, or all booleans. Mixed arrays such as ['1', 2] are rejected client-side with ChromaValueError.

Source

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

  const validateMetadataListValue = (key: string, v: unknown[]): void => {
    if (v.length === 0) {
      throw new ChromaValueError(
        `Expected metadata list value for key '${key}' to be non-empty`,
      );
    }
    const firstType = typeof v[0];
    for (const item of v) {
      if (
        typeof item !== "string" &&
        typeof item !== "number" &&
        typeof item !== "boolean"
      ) {
        throw new ChromaValueError(
          `Expected metadata list value for key '${key}' to contain only strings, numbers, or booleans, got ${typeof item}`,
        );
      }
      if (typeof item !== firstType) {
        throw new ChromaValueError(
          `Expected metadata list value for key '${key}' to contain only the same type, got mixed types`,
        );
      }
    }
  };

  for (const [key, v] of Object.entries(metadata)) {
    if (
      v === null ||
      v === undefined ||
      typeof v === "string" ||
      typeof v === "number" ||
      typeof v === "boolean"
    ) {
      continue;
    }
    if (validateSparseVector(v)) {
      continue;

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Coerce the whole list to one type before the call, e.g. list.map(Number) or list.map(String).
  2. Normalize at ingestion so a given key always carries one type.
  3. Assert type uniformity across each list value in a unit test of your metadata builder.

Example fix

// before
metadatas: [{ values: ['1', 2, '3'] }]

// after
metadatas: [{ values: ['1', 2, '3'].map(Number) }]
Defensive patterns

Strategy: validation

Validate before calling

const homogeneous = (v) => !Array.isArray(v) || v.every(item => typeof item === typeof v[0]);
const safe = Object.fromEntries(Object.entries(meta).filter(([, v]) => homogeneous(v)));

Type guard

const isHomogeneousList = (v: unknown): v is unknown[] =>
  Array.isArray(v) && v.every(item => typeof item === typeof v[0]);

Try / catch

try {
  await collection.add({ ids, metadatas });
} catch (e) {
  if ((e as Error).message.includes('mixed types')) {
    // coerce the offending list to one type (map(String) or map(Number)) and retry
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: metadatas: [{ ids: [1, '2', 3] }]. Parsing CSV/JSON where numbers sometimes arrive as strings, producing ['1', 2]. Booleans mixed with 0/1 encodings, e.g. [true, 1].

Common situations: Heterogeneous API responses; loose parsing that leaves some values as strings; merging data from sources with different type conventions for the same key.

Related errors


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