chroma-core/chroma · error · ValueError

Expected documents to be a non-empty list, got {len(document

Error message

Expected documents to be a non-empty list, got {len(documents)} documents

What it means

validate_documents rejects an empty documents list (len == 0). At least one document must accompany an add/upsert call; the message echoes the zero count. Individual None entries are permitted only when embeddings are also present (nullable=True), but an entirely empty list is never valid.

Source

Thrown at chromadb/api/types.py:1447

        raise ValueError(
            f"Expected sparse vectors to be a non-empty list, got {len(vectors)} sparse vectors"
        )
    for i, vector in enumerate(vectors):
        if not isinstance(vector, SparseVector):
            raise ValueError(
                f"Expected SparseVector instance at position {i}, got {type(vector).__name__}"
            )
    return vectors


def validate_documents(documents: Documents, nullable: bool = False) -> None:
    """Validates documents to ensure it is a list of strings"""
    if not isinstance(documents, list):
        raise ValueError(
            f"Expected documents to be a list, got {type(documents).__name__}"
        )
    if len(documents) == 0:
        raise ValueError(
            f"Expected documents to be a non-empty list, got {len(documents)} documents"
        )
    for document in documents:
        # If embeddings are present, some documents can be None
        if document is None and nullable:
            continue
        if not is_document(document):
            raise ValueError(f"Expected document to be a str, got {document}")


def validate_images(images: Images) -> None:
    """Validates images to ensure it is a list of numpy arrays"""
    if not isinstance(images, list):
        raise ValueError(f"Expected images to be a list, got {type(images).__name__}")
    if len(images) == 0:
        raise ValueError(
            f"Expected images to be a non-empty list, got {len(images)} images"
        )

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Guard the call: if documents: collection.add(ids=ids, documents=documents)
  2. Fix or loosen the upstream loader/chunker so batches are non-empty when data exists
  3. Log batch sizes during ingestion to catch silent zero-length batches early

Example fix

# before
collection.add(ids=ids, documents=chunks)  # chunks == []

# after
if chunks:
    collection.add(ids=ids, documents=chunks)
else:
    logger.warning("skipped empty batch for %s", source)
Defensive patterns

Strategy: validation

Validate before calling

def add_batch(collection, ids, documents, metadatas=None):
    if not documents:
        logger.warning("skipping empty document batch")
        return False
    collection.add(ids=ids, documents=documents, metadatas=metadatas)
    return True

Type guard

def is_non_empty_document_list(docs) -> bool:
    return isinstance(docs, list) and len(docs) > 0 and all(isinstance(d, str) for d in docs)

Try / catch

try:
    collection.add(ids=ids, documents=chunks, metadatas=metas)
except ValueError as e:
    if "non-empty list, got 0 documents" in str(e):
        logger.warning("empty batch from loader — skipped")
    else:
        raise

Prevention

When it happens

Trigger: collection.add(ids=[], documents=[]) — an upstream loader/chunker produced zero rows; a batch loop iterating an empty file set; filtering that removed every document from the batch.

Common situations: Directory ingestion where a folder contains no valid files; chunkers returning [] for blank/tiny documents; ETL stages filtering aggressively then still calling add(); empty-batch edge case in scheduled jobs.

Related errors


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