chroma-core/chroma · error · ValueError
Expected sparse vectors to be a non-empty list, got {len(vec
Error message
Expected sparse vectors to be a non-empty list, got {len(vectors)} sparse vectors What it means
validate_sparse_vectors rejects an empty list (len == 0). At least one SparseVector must be present, mirroring the dense-embeddings rule; the message echoes the zero count.
Source
Thrown at chromadb/api/types.py:1429
def validate_sparse_vectors(vectors: SparseVectors) -> SparseVectors:
"""Validates sparse vectors to ensure it is a non-empty list of SparseVector instances.
This function validates the structure and types of sparse vectors returned by
SparseEmbeddingFunction implementations. It ensures:
- Vectors is a list
- List is non-empty
- All items are SparseVector instances
Note: Individual SparseVector validation (sorted indices, non-negative values, etc.)
happens automatically in SparseVector.__post_init__ when each instance is created.
This function only validates the list structure and instance types.
"""
if not isinstance(vectors, list):
raise ValueError(
f"Expected sparse vectors to be a list, got {type(vectors).__name__}"
)
if len(vectors) == 0:
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(View on GitHub (pinned to aecdd12c8a)
Solutions
- Skip the call when there is nothing to embed: if not texts: return []
- Guard at the call site: if sparse_vectors: collection.add(..., sparse_vectors=sparse_vectors)
- Fix upstream filtering that dropped every row in the batch
Example fix
# before
sv = sparse_ef(texts) # texts == [] -> []
collection.add(ids=ids, sparse_vectors=sv, documents=texts)
# after
if texts:
sv = sparse_ef(texts)
collection.add(ids=ids, sparse_vectors=sv, documents=texts) Defensive patterns
Strategy: validation
Validate before calling
def sparse_add(collection, ids, texts, sparse_ef):
if not texts:
return # nothing to embed — skip instead of calling with []
sv = sparse_ef(texts)
if not sv:
raise ValueError("sparse embedding function returned an empty list for non-empty input")
collection.add(ids=ids, documents=texts, sparse_vectors=sv) Type guard
def is_non_empty_sparse_list(v) -> bool:
return isinstance(v, list) and len(v) > 0 Try / catch
try:
collection.query(query_texts=[q], sparse_vectors=sv if sv else None)
except ValueError as e:
if "non-empty list, got 0 sparse vectors" in str(e):
logger.warning("empty sparse batch skipped")
else:
raise Prevention
- Short-circuit empty text batches before invoking the sparse embedder
- Assert len(texts) == len(sparse_vectors) after every EF call — catches empty/unbalanced outputs
- Guard hybrid pipelines where either dense or sparse side can be empty
When it happens
Trigger: A SparseEmbeddingFunction invoked on an empty input list returning []; calling add()/query() with sparse_vectors=[]; batch loops that don't skip empty batches.
Common situations: Hybrid-search pipelines where chunking or filtering produced zero texts for one batch; per-file processing of empty files; reusing the dense-pipeline guard code that was never written.
Related errors
- Expected embeddings to be a list with at least one item, got
- Expected documents to be a non-empty list, got {len(document
- ${respBody?.message}
- Could not serialize collection configuration
- If sourceKey is provided then embeddingFunction must also be
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/af0d86feee70a75b.
Report an issue: GitHub.