chroma-core/chroma · error · ValueError
All weights must be non-negative
Error message
All weights must be non-negative
What it means
Weights in Chroma's Rrf scale each strategy's contribution weight_i / (k + rank_i), and negative weights would invert a strategy's ranking order rather than weight it — so Rrf.to_dict() rejects any weight < 0 with this ValueError at serialization/query time. Zero weights are allowed (they disable a strategy) unless normalize=True makes the total zero.
Source
Thrown at chromadb/execution/expression/operator.py:1215
"""Convert RRF to a composition of existing expression operators.
Builds: -sum(weight_i / (k + rank_i)) for each rank
Using Python's overloaded operators for cleaner code.
"""
# Validate RRF parameters
if not self.ranks:
raise ValueError("RRF requires at least one rank")
if self.k <= 0:
raise ValueError(f"k must be positive, got {self.k}")
# Validate weights if provided
if self.weights is not None:
if len(self.weights) != len(self.ranks):
raise ValueError(
f"Number of weights ({len(self.weights)}) must match number of ranks ({len(self.ranks)})"
)
if any(w < 0.0 for w in self.weights):
raise ValueError("All weights must be non-negative")
# Populate weights with 1.0 if not provided
weights = self.weights if self.weights else [1.0] * len(self.ranks)
# Normalize weights if requested
if self.normalize:
weight_sum = sum(weights)
if weight_sum == 0:
raise ValueError("Sum of weights must be positive when normalize=True")
weights = [w / weight_sum for w in weights]
# Zip weights with ranks and build terms: weight / (k + rank)
terms = [w / (self.k + rank) for w, rank in zip(weights, self.ranks)]
# Sum all terms - guaranteed to have at least one
rrf_sum: Rank = terms[0]
for term in terms[1:]:
rrf_sum = rrf_sum + termView on GitHub (pinned to aecdd12c8a)
Solutions
- Use non-negative weights; to demote a strategy, lower its weight toward 0.0 instead of negating it
- If weights are computed, clamp: weights = [max(0.0, w) for w in weights]
- Validate all(w >= 0 for w in weights) before constructing/serializing Rrf and fail with your own message
- Re-check the intent: inverting a ranking is not achievable via negative RRF weight; use a different rank expression if that is the goal
Example fix
# before rrf = Rrf(ranks=ranks, weights=[-0.5, 2.0], k=60) # after rrf = Rrf(ranks=ranks, weights=[0.5, 2.0], k=60)
Defensive patterns
Strategy: validation
Validate before calling
if any(w < 0 for w in weights):
raise ValueError(f"RRF weights must be non-negative: {weights}")
rrf = Rrf(ranks=ranks, weights=weights, k=60) Type guard
def non_negative_weights(weights) -> bool:
return all(isinstance(w, (int, float)) and w >= 0 for w in weights) Try / catch
try:
plan = rrf.to_dict()
except ValueError as e:
raise ValueError(f"invalid RRF weights {rrf.weights}: {e}") from e Prevention
- Use 0.0 to disable a strategy, never a negative weight
- Clamp computed weights: max(0.0, w) before passing them in
- Remember negative RRF weights cannot invert a ranking; redesign the expression instead
When it happens
Trigger: Rrf(ranks=[...], weights=[-1.0, 2.0], ...) then .to_dict() or query execution; commonly a sign error in tuning code, or weights computed as a difference that can go negative.
Common situations: See trigger scenarios.
Related errors
- Sum of weights must be positive when normalize=True
- RRF requires at least one rank
- k must be positive, got {self.k}
- Number of weights ({len(self.weights)}) must match number of
- $sum requires at least 2 ranks, got {len(ranks_data)}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/efa6f19f57b39a39.
Report an issue: GitHub.