chroma-core/chroma · error · TypeError

Number of requested results {n_results}, cannot be negative,

Error message

Number of requested results {n_results}, cannot be negative, or zero.

What it means

validate_n_results raises a TypeError (not ValueError) when n_results <= 0, because the underlying HNSW index cannot serve zero or negative result counts. This fires after the int-type check passes, so the value is a genuine int that is 0 or negative.

Source

Thrown at chromadb/api/types.py:1366

            raise ValueError(
                f"Expected include item to be one of {', '.join(valid_items)}, got {item}"
            )

        if dissalowed is not None and any(item == e for e in dissalowed):
            raise ValueError(
                f"Include item cannot be one of {', '.join(dissalowed)}, got {item}"
            )


def validate_n_results(n_results: int) -> int:
    """Validates n_results to ensure it is a positive Integer. Since hnswlib does not allow n_results to be negative."""
    # Check Number of requested results
    if not isinstance(n_results, int):
        raise ValueError(
            f"Expected requested number of results to be a int, got {n_results}"
        )
    if n_results <= 0:
        raise TypeError(
            f"Number of requested results {n_results}, cannot be negative, or zero."
        )
    return n_results


def validate_embeddings(embeddings: Embeddings) -> Embeddings:
    """Validates embeddings to ensure it is a list of numpy arrays of ints, or floats"""
    if not isinstance(embeddings, (list, np.ndarray)):
        raise ValueError(
            f"Expected embeddings to be a list, got {type(embeddings).__name__}"
        )
    if len(embeddings) == 0:
        raise ValueError(
            f"Expected embeddings to be a list with at least one item, got {len(embeddings)} embeddings"
        )
    if not all([isinstance(e, np.ndarray) for e in embeddings]):
        raise ValueError(
            "Expected each embedding in the embeddings to be a numpy array, got "

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Clamp before the call: n_results=max(1, k)
  2. Skip the query entirely when the computed top-k is 0 instead of calling with n_results=0
  3. Treat 0 as a sentinel and substitute a sensible default (e.g. 10)

Example fix

# before
k = min(user_top_k, collection.count())  # 0 when collection is empty
results = collection.query(query_embeddings=[q], n_results=k)

# after
k = min(user_top_k, collection.count())
if k <= 0:
    results = {"ids": [[]], "documents": [[]]}
else:
    results = collection.query(query_embeddings=[q], n_results=k)
Defensive patterns

Strategy: validation

Validate before calling

def safe_n_results(k, default=10) -> int:
    try:
        k = int(k)
    except (TypeError, ValueError):
        k = default
    return max(1, k)

res = collection.query(query_embeddings=[q], n_results=safe_n_results(min(user_k, collection.count())))

Type guard

def is_valid_n_results(n) -> bool:
    return isinstance(n, int) and not isinstance(n, bool) and n >= 1

Try / catch

try:
    res = collection.query(query_texts=[q], n_results=k)
except TypeError as e:  # note: this check raises TypeError, not ValueError
    if "cannot be negative, or zero" in str(e):
        res = collection.query(query_texts=[q], n_results=1)
    else:
        raise

Prevention

When it happens

Trigger: collection.query(query_texts=..., n_results=0) — commonly a computed top-k that evaluated to 0, e.g. min(len(collection), user_k) with an empty collection, max(0, something), or a default of 0 meaning 'not set'.

Common situations: top_k = min(user_k, collection.count()) returning 0 on a fresh collection; config defaults of 0; pagination math floor-dividing to 0; user-supplied limit=0 intended to mean 'no limit'.

Related errors


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