{"record":{"id":"dac658e30f39e0b4","repo":"chroma-core/chroma","slug":"sum-of-weights-must-be-positive-when-normalize-tru","errorCode":null,"errorMessage":"Sum of weights must be positive when normalize=True","messagePattern":"Sum of weights must be positive when normalize=True","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":1224,"sourceCode":"            raise ValueError(f\"k must be positive, got {self.k}\")\n\n        # Validate weights if provided\n        if self.weights is not None:\n            if len(self.weights) != len(self.ranks):\n                raise ValueError(\n                    f\"Number of weights ({len(self.weights)}) must match number of ranks ({len(self.ranks)})\"\n                )\n            if any(w < 0.0 for w in self.weights):\n                raise ValueError(\"All weights must be non-negative\")\n\n        # Populate weights with 1.0 if not provided\n        weights = self.weights if self.weights else [1.0] * len(self.ranks)\n\n        # Normalize weights if requested\n        if self.normalize:\n            weight_sum = sum(weights)\n            if weight_sum == 0:\n                raise ValueError(\"Sum of weights must be positive when normalize=True\")\n            weights = [w / weight_sum for w in weights]\n\n        # Zip weights with ranks and build terms: weight / (k + rank)\n        terms = [w / (self.k + rank) for w, rank in zip(weights, self.ranks)]\n\n        # Sum all terms - guaranteed to have at least one\n        rrf_sum: Rank = terms[0]\n        for term in terms[1:]:\n            rrf_sum = rrf_sum + term\n\n        # Negate (RRF gives higher scores for better, Chroma needs lower for better)\n        return (-rrf_sum).to_dict()\n\n\n@dataclass\nclass Select:\n    \"\"\"Selection configuration for search results.\n","sourceCodeStart":1206,"sourceCodeEnd":1242,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L1206-L1242","documentation":"With normalize=True, Chroma's Rrf rescales weights to sum to 1.0 by dividing each by sum(weights); a zero total would divide by zero, so Rrf.to_dict() raises this ValueError when all supplied weights are 0.0. Note the weights defaulting step treats only an empty/None list as 'unset' — an explicit all-zero list survives the non-negative check and fails here.","triggerScenarios":"Rrf(ranks=[...], weights=[0.0, 0.0], normalize=True) then .to_dict() or query execution; also a longer weights vector that is entirely zeros, or weights computed by a formula (e.g. softmax at temperature ~0, or scores rounded down) that yields all zeros.","commonSituations":"Strategies disabled by setting their weight to 0 while normalize=True is kept on; weight vectors derived from external relevance data that can be all-zero for some tenants/queries; tuning loops that sweep weights including the all-zero corner.","solutions":["Give at least one strategy a strictly positive weight, e.g. weights=[0.0, 1.0]","Drop normalize=True if you intentionally use relative (unnormalized) weights","Validate before serializing: if normalize and sum(weights) <= 0: raise your own config error","Guard computed weights: if total == 0, fall back to equal weights [1.0]*len(ranks) or skip the query"],"exampleFix":"# before\nrrf = Rrf(ranks=ranks, weights=[0.0, 0.0], normalize=True)\n\n# after\nrrf = Rrf(ranks=ranks, weights=[0.0, 1.0], normalize=True)  # -> [0.0, 1.0]","handlingStrategy":"validation","validationCode":"if normalize and sum(weights) <= 0:\n    raise ValueError(f\"weights sum to {sum(weights)}; need > 0 when normalize=True\")\nrrf = Rrf(ranks=ranks, weights=weights, normalize=True, k=60)","typeGuard":"def normalizable_weights(weights) -> bool:\n    return sum(weights) > 0","tryCatchPattern":"try:\n    plan = rrf.to_dict()\nexcept ValueError as e:\n    raise ValueError(\n        f\"invalid RRF weights {rrf.weights} for normalize={rrf.normalize}: {e}\"\n    ) from e","preventionTips":["Keep at least one strictly positive weight when normalize=True","If strategies are disabled via zero weights, either drop normalize=True or rebuild the weights list without them","Guard computed weight vectors with an all-zero check and fall back to equal weights"],"tags":["chromadb","rrf","rank-expression","validation","weights","divide-by-zero"],"backgroundTag":"rrf-invalid-parameters","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}