{"record":{"id":"20bf692ae8187792","repo":"chroma-core/chroma","slug":"min-requires-at-least-2-ranks-got-len-ranks-dat","errorCode":null,"errorMessage":"$min requires at least 2 ranks, got {len(ranks_data)}","messagePattern":"\\$min requires at least 2 ranks, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":859,"sourceCode":"            if len(ranks_data) < 2:\n                raise ValueError(\n                    f\"$max requires at least 2 ranks, got {len(ranks_data)}\"\n                )\n\n            ranks = [Rank.from_dict(r) for r in ranks_data]\n            result = ranks[0]\n            for r in ranks[1:]:\n                result = result.max(r)\n            return result\n\n        elif op == \"$min\":\n            ranks_data = data[\"$min\"]\n            if not isinstance(ranks_data, (list, tuple)):\n                raise TypeError(\n                    f\"$min requires a list, got {type(ranks_data).__name__}\"\n                )\n            if len(ranks_data) < 2:\n                raise ValueError(\n                    f\"$min requires at least 2 ranks, got {len(ranks_data)}\"\n                )\n\n            ranks = [Rank.from_dict(r) for r in ranks_data]\n            result = ranks[0]\n            for r in ranks[1:]:\n                result = result.min(r)\n            return result\n\n        else:\n            raise ValueError(f\"Unknown rank operator: {op}\")\n\n    # Arithmetic operators\n    def __add__(self, other: Union[\"Rank\", float, int]) -> \"Sum\":\n        \"\"\"Addition: rank1 + rank2 or rank + value\"\"\"\n        other_rank = Val(other) if isinstance(other, (int, float)) else other\n        # Flatten if already Sum\n        if isinstance(self, Sum):","sourceCodeStart":841,"sourceCodeEnd":877,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L841-L877","documentation":"$min combines at least two rank expressions via successive pairwise minimums, so Chroma's parser rejects payloads with fewer than two operands. This ValueError from Rank.from_dict fires when the $min list has 0 or 1 elements.","triggerScenarios":"Rank.from_dict({'$min': []}) or {'$min': [single_rank]} — e.g. a cap built over a dynamic list of bounds where only one remains, or a lone operand wrapped needlessly.","commonSituations":"Configurable clamping where the bounds list collapses to one element; 'consistency' wrapping of a single term; trimmed test fixtures.","solutions":["Pass at least two operands, or drop the wrapper and pass the single rank dict directly","When capping against a bound, always include both: {\"$min\": [rank, {\"$val\": bound}]}","Branch when building dynamically: expr = ranks[0] if len(ranks) == 1 else {'$min': ranks}","Validate operand count before deserialization"],"exampleFix":"# before\nexpr = {\"$min\": [knn_rank]}\n\n# after\nexpr = {\"$min\": [knn_rank, {\"$val\": 1.0}]}","handlingStrategy":"validation","validationCode":"def valid_min_expr(expr):\n    return (\n        isinstance(expr, dict) and set(expr) == {\"$min\"}\n        and isinstance(expr[\"$min\"], (list, tuple))\n        and len(expr[\"$min\"]) >= 2\n    )\n\nif not valid_min_expr(rank_expr):\n    raise ValueError(f\"$min needs >= 2 operands: {rank_expr!r}\")","typeGuard":"def is_min_expr(d) -> bool:\n    return (isinstance(d, dict) and set(d) == {\"$min\"}\n            and isinstance(d[\"$min\"], (list, tuple))\n            and len(d[\"$min\"]) >= 2)","tryCatchPattern":"try:\n    rank = Rank.from_dict(rank_expr)\nexcept (TypeError, ValueError) as e:\n    raise ValueError(f\"invalid rank expression {rank_expr!r}: {e}\") from e","preventionTips":["A cap always has two sides: include the bound as {\"$val\": b}","Pass a lone operand through unwrapped","Validate bound lists built from config before folding them into $min"],"tags":["chromadb","rank-expression","validation","deserialization","clamping"],"backgroundTag":"query-expression-validation","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}