chroma-core/chroma · error · ValueError

Rank dict must contain exactly one operator, got {len(data)}

Error message

Rank dict must contain exactly one operator, got {len(data)}

What it means

A rank dict must contain exactly one operator key ($val, $knn, $sum, ...). Two or more keys in the same dict raise ValueError because the grammar has no sibling-key composition: combining expressions is expressed by nesting them under arithmetic operators, never by merging keys into one dict.

Source

Thrown at chromadb/execution/expression/operator.py:677

        - {"$knn": {...}} -> Knn(...)
        - {"$sum": [ranks]} -> rank1 + rank2 + ...
        - {"$sub": {"left": ..., "right": ...}} -> left - right
        - {"$mul": [ranks]} -> rank1 * rank2 * ...
        - {"$div": {"left": ..., "right": ...}} -> left / right
        - {"$abs": rank} -> abs(rank)
        - {"$exp": rank} -> rank.exp()
        - {"$log": rank} -> rank.log()
        - {"$max": [ranks]} -> rank1.max(rank2).max(rank3)...
        - {"$min": [ranks]} -> rank1.min(rank2).min(rank3)...
        """
        if not isinstance(data, dict):
            raise TypeError(f"Expected dict for Rank, got {type(data).__name__}")

        if not data:
            raise ValueError("Rank dict cannot be empty")

        if len(data) != 1:
            raise ValueError(
                f"Rank dict must contain exactly one operator, got {len(data)}"
            )

        op = next(iter(data.keys()))

        if op == "$val":
            value = data["$val"]
            if not isinstance(value, (int, float)):
                raise TypeError(f"$val requires a number, got {type(value).__name__}")
            return Val(value)

        elif op == "$knn":
            knn_data = data["$knn"]
            if not isinstance(knn_data, dict):
                raise TypeError(f"$knn requires a dict, got {type(knn_data).__name__}")

            if "query" not in knn_data:
                raise ValueError("$knn requires 'query' field")

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Express combinations with arithmetic operators: {'$sum': [{'$val': 0.5}, {'$knn': {...}}]}.
  2. Use the class API: Val(0.5) + Knn(query=[...]).
  3. Never dict-merge (** or |=) rank expressions.

Example fix

# before
Search(rank={'$val': 0.5, '$knn': {'query': emb}})   # 2 keys -> ValueError

# after
Search(rank={'$sum': [{'$val': 0.5}, {'$knn': {'query': emb}}]})
Defensive patterns

Strategy: validation

Validate before calling

def valid_rank_shape(node) -> bool:
    return isinstance(node, dict) and len(node) == 1

if rank_cfg is not None and not valid_rank_shape(rank_cfg):
    raise ValueError(f'rank must have exactly one operator, got {list(rank_cfg)}')
Search(rank=rank_cfg)

Type guard

def is_single_operator_dict(node) -> bool:
    return isinstance(node, dict) and len(node) == 1 and next(iter(node), '').startswith('$')

Prevention

When it happens

Trigger: Search(rank={'$val': 0.5, '$knn': {'query': [...]}}); dict-merging two expressions ({**a, **b}); nested case {'$sum': [{'$val': 1, '$abs': {'$val': -1}}]} where the inner dict has 2 keys.

Common situations: Trying to 'add a boost' by merging a constant into an existing Knn dict; config systems that deep-merge rank blocks; assuming sibling keys behave like $and when building weighted scores.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/6341fa1afac28a97. Report an issue: GitHub.