chroma-core/chroma · error · ValueError
$sum requires at least 2 ranks, got {len(ranks_data)}
Error message
$sum requires at least 2 ranks, got {len(ranks_data)} What it means
Chroma's execution engine deserializes rank (reranking) expressions from JSON via Rank.from_dict. The $sum operator folds several rank expressions into one Sum, and the parser requires its payload to be a list with at least two rank dicts, because a Sum with fewer than two operands is meaningless (the serializer side only ever emits >= 2 operands after flattening). This ValueError fires when the $sum payload list has 0 or 1 elements.
Source
Thrown at chromadb/execution/expression/operator.py:758
f"$knn return_rank must be a boolean, got {type(return_rank).__name__}"
)
return Knn(
query=query,
key=key,
limit=limit,
default=knn_data.get("default"),
return_rank=return_rank,
)
elif op == "$sum":
ranks_data = data["$sum"]
if not isinstance(ranks_data, (list, tuple)):
raise TypeError(
f"$sum requires a list, got {type(ranks_data).__name__}"
)
if len(ranks_data) < 2:
raise ValueError(
f"$sum requires at least 2 ranks, got {len(ranks_data)}"
)
ranks = [Rank.from_dict(r) for r in ranks_data]
result = ranks[0]
for r in ranks[1:]:
result = result + r
return result
elif op == "$sub":
sub_data = data["$sub"]
if not isinstance(sub_data, dict):
raise TypeError(
f"$sub requires a dict with 'left' and 'right', got {type(sub_data).__name__}"
)
if "left" not in sub_data or "right" not in sub_data:
raise ValueError("$sub requires 'left' and 'right' fields")
View on GitHub (pinned to aecdd12c8a)
Solutions
- If there is only one rank, drop the $sum wrapper and pass the rank dict itself (e.g. {'$knn': {...}} instead of {'$sum': [{'$knn': {...}}]})
- If building dynamically, branch on length: expr = ranks[0] if len(ranks) == 1 else {'$sum': ranks}
- Build expressions with the Python operator API (rank1 + rank2 ... then .to_dict()) instead of hand-writing operator dicts, so the serializer emits valid shapes
- Validate the $sum payload shape with a guard before calling Rank.from_dict or sending the query
Example fix
# before
ranks = [{"$knn": {"query": q, "return_rank": True}} for q in queries] # may be length 1
expr = {"$sum": ranks}
# after
ranks = [{"$knn": {"query": q, "return_rank": True}} for q in queries]
expr = ranks[0] if len(ranks) == 1 else {"$sum": ranks} Defensive patterns
Strategy: validation
Validate before calling
def valid_sum_expr(expr):
return (
isinstance(expr, dict) and set(expr) == {"$sum"}
and isinstance(expr["$sum"], (list, tuple))
and len(expr["$sum"]) >= 2
)
if not valid_sum_expr(rank_expr):
raise ValueError(f"invalid $sum expression: {rank_expr!r}") Type guard
def is_sum_expr(d) -> bool:
return (isinstance(d, dict) and set(d) == {"$sum"}
and isinstance(d["$sum"], (list, tuple))
and len(d["$sum"]) >= 2) Try / catch
try:
rank = Rank.from_dict(rank_expr)
except (TypeError, ValueError) as e:
raise ValueError(f"invalid rank expression {rank_expr!r}: {e}") from e Prevention
- Build rank expressions with Python operator overloading (r1 + r2).to_dict() instead of hand-writing $sum dicts
- When fusing a dynamic number of ranks, special-case len == 1 to pass the rank unwrapped
- Add a round-trip test: Rank.from_dict(expr.to_dict()) for every expression your code emits
When it happens
Trigger: Calling Rank.from_dict({'$sum': [...]}) directly, or submitting a query whose rank expression contains {'$sum': []} or {'$sum': [<single rank dict>]}. Most often the list is built dynamically over a variable number of searches and collapses to one element at runtime.
Common situations: Hybrid/multi-query search code that fuses N KNN rankings with $sum where a filter reduces N to 1; hand-written rank-expression JSON that wraps a lone term in $sum 'for consistency'; test fixtures copied from a two-query example and trimmed to one.
Related errors
- $mul requires at least 2 ranks, got {len(ranks_data)}
- $sub requires a dict with 'left' and 'right', got {type(sub_
- $sub requires 'left' and 'right' fields
- $mul requires a list, got {type(ranks_data).__name__}
- $div requires a dict with 'left' and 'right', got {type(div_
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/88b63364d4327a87.
Report an issue: GitHub.