chroma-core/chroma · error · ChromaValueError

Expected metadata list value for key '${key}' to be non-empt

Error message

Expected metadata list value for key '${key}' to be non-empty

What it means

The inner list validator in validateMetadata (validateMetadataListValue) throws when a metadata key holds an empty array. Array-valued metadata (string[], number[], boolean[]) must contain at least one element; an empty list is rejected client-side with ChromaValueError before the request is sent. Use null or omit the key to express 'no value'.

Source

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

};

/**
 * Validates metadata object for correct types and non-emptiness.
 * @param metadata - Metadata object to validate
 * @throws ChromaValueError if metadata is invalid
 */
export const validateMetadata = (metadata?: Metadata) => {
  if (!metadata) {
    return;
  }

  if (Object.keys(metadata).length === 0) {
    throw new ChromaValueError("Expected metadata to be non-empty");
  }

  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`,
        );

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Remove the key or set it to null when the list is empty.
  2. Guard at build time: keep the key only when list.length > 0.
  3. Run a per-key array check before calling add()/upsert().

Example fix

// before
const meta = { tags }; // tags === []

// after
const meta = tags.length ? { tags } : null;
Defensive patterns

Strategy: validation

Validate before calling

const dropEmptyLists = (m) => {
  if (!m) return null;
  const out = {};
  for (const [k, v] of Object.entries(m)) {
    if (!Array.isArray(v) || v.length > 0) out[k] = v;
  }
  return Object.keys(out).length ? out : null;
};
const safe = metadatas.map(dropEmptyLists);

Type guard

const isNonEmptyList = (v: unknown): v is [unknown, ...unknown[]] =>
  Array.isArray(v) && v.length > 0;

Try / catch

try {
  await collection.add({ ids, metadatas });
} catch (e) {
  if ((e as Error).message.includes('list value for key') && (e as Error).message.includes('non-empty')) {
    // strip empty list keys, then retry once with cleaned metadata
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: collection.add() with metadatas: [{ tags: [] }]. Tag/category lists collected per record where a record has none, e.g. { categories: filteredList } with filteredList empty after filtering.

Common situations: Tag arrays derived from user selection or filtering; optional list fields in an ingestion pipeline; defaulting missing lists to [] instead of null.

Related errors


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