{"record":{"id":"d1d356154ac9b924","repo":"chroma-core/chroma","slug":"sum-requires-a-list-got-type-ranks-data-name","errorCode":null,"errorMessage":"$sum requires a list, got {type(ranks_data).__name__}","messagePattern":"\\$sum requires a list, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":754,"sourceCode":"\n            return_rank = knn_data.get(\"return_rank\", False)\n            if not isinstance(return_rank, bool):\n                raise TypeError(\n                    f\"$knn return_rank must be a boolean, got {type(return_rank).__name__}\"\n                )\n\n            return Knn(\n                query=query,\n                key=key,\n                limit=limit,\n                default=knn_data.get(\"default\"),\n                return_rank=return_rank,\n            )\n\n        elif op == \"$sum\":\n            ranks_data = data[\"$sum\"]\n            if not isinstance(ranks_data, (list, tuple)):\n                raise TypeError(\n                    f\"$sum requires a list, got {type(ranks_data).__name__}\"\n                )\n            if len(ranks_data) < 2:\n                raise ValueError(\n                    f\"$sum 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 + r\n            return result\n\n        elif op == \"$sub\":\n            sub_data = data[\"$sub\"]\n            if not isinstance(sub_data, dict):\n                raise TypeError(\n                    f\"$sub requires a dict with 'left' and 'right', got {type(sub_data).__name__}\"","sourceCodeStart":736,"sourceCodeEnd":772,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L736-L772","documentation":"$sum combines rank expressions and takes a list of at least two rank dicts: {'$sum': [rank1, rank2, ...]}. Passing anything that is not a list/tuple - a dict or bare value - raises TypeError before element validation. $sum/$mul/$max/$min are n-ary list-shaped operators, while $sub/$div take {'left', 'right'} dicts.","triggerScenarios":"Search(rank={'$sum': {'left': {...}, 'right': {...}}}) - using $sub's shape with $sum; {'$sum': {'$val': 1}} trying to 'sum' a single term; {'$sum': 'expr'} passing a string.","commonSituations":"Mixing up operator arities when hand-writing expressions; template code emitting the same payload shape for every operator; building weighted scores and pairing $sum with a dict by analogy to $sub.","solutions":["Use a list with >= 2 rank dicts: {'$sum': [{'$val': 1}, {'$knn': {...}}]}.","For two-term subtraction/division switch operators: {'$sub': {'left': ..., 'right': ...}} or '$div'.","For a single term, drop the wrapper - the child rank alone is the expression."],"exampleFix":"# before\nSearch(rank={'$sum': {'left': {'$val': 1}, 'right': {'$val': 2}}})   # -> TypeError: got dict\n\n# after\nSearch(rank={'$sum': [{'$val': 1}, {'$val': 2}]})\n# two-term binary alternative\nSearch(rank={'$sub': {'left': {'$val': 1}, 'right': {'$val': 2}}})","handlingStrategy":"type-guard","validationCode":"def rank_sum(*terms):\n    if len(terms) < 2:\n        raise ValueError('$sum needs at least 2 ranks')\n    return {'$sum': list(terms)}\n\nSearch(rank=rank_sum({'$val': 1}, {'$knn': {'query': emb}}))","typeGuard":"def is_nary_rank_payload(arg) -> bool:\n    return (\n        isinstance(arg, (list, tuple))\n        and len(arg) >= 2\n        and all(isinstance(t, dict) for t in arg)\n    )","tryCatchPattern":null,"preventionTips":["Memorize the two arities: $sum/$mul/$max/$min take lists; $sub/$div take {'left', 'right'} dicts.","Build expressions with helper functions or the class API (+, -, *, /) instead of literals.","A single-term $sum is pointless - pass the term itself."],"tags":["validation","typeerror","rank","sum","expression","chromadb"],"backgroundTag":"type-validation-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}