chroma-core/chroma · error · TypeError
$abs requires a rank dict, got {type(child_data).__name__}
Error message
$abs requires a rank dict, got {type(child_data).__name__} What it means
$abs is a unary rank operator that takes exactly one nested rank expression (e.g. abs of a difference) and expects its payload to be a single rank dict. Rank.from_dict raises this TypeError when the $abs payload is not a dict — most commonly a bare number or a list wrapping the operand.
Source
Thrown at chromadb/execution/expression/operator.py:814
return result
elif op == "$div":
div_data = data["$div"]
if not isinstance(div_data, dict):
raise TypeError(
f"$div requires a dict with 'left' and 'right', got {type(div_data).__name__}"
)
if "left" not in div_data or "right" not in div_data:
raise ValueError("$div requires 'left' and 'right' fields")
left = Rank.from_dict(div_data["left"])
right = Rank.from_dict(div_data["right"])
return left / right
elif op == "$abs":
child_data = data["$abs"]
if not isinstance(child_data, dict):
raise TypeError(
f"$abs requires a rank dict, got {type(child_data).__name__}"
)
return abs(Rank.from_dict(child_data))
elif op == "$exp":
child_data = data["$exp"]
if not isinstance(child_data, dict):
raise TypeError(
f"$exp requires a rank dict, got {type(child_data).__name__}"
)
return Rank.from_dict(child_data).exp()
elif op == "$log":
child_data = data["$log"]
if not isinstance(child_data, dict):
raise TypeError(
f"$log requires a rank dict, got {type(child_data).__name__}"
)View on GitHub (pinned to aecdd12c8a)
Solutions
- Pass one unwrapped rank dict: {"$abs": {"$val": 5}} or {"$abs": {"$sub": {...}}}
- Wrap literals in $val: use {"$abs": {"$val": 5}} for abs of a constant
- Build in Python as abs(rank_expr).to_dict()
- Guard: isinstance(expr['$abs'], dict) before deserialization
Example fix
# before
expr = {"$abs": [{"$sub": {"left": a, "right": b}}]}
# after
expr = {"$abs": {"$sub": {"left": a, "right": b}}} Defensive patterns
Strategy: validation
Validate before calling
def valid_abs_expr(expr):
return (
isinstance(expr, dict) and set(expr) == {"$abs"}
and isinstance(expr["$abs"], dict)
)
if not valid_abs_expr(rank_expr):
raise ValueError(f"$abs payload must be a single rank dict: {rank_expr!r}") Type guard
def is_abs_expr(d) -> bool:
return (isinstance(d, dict) and set(d) == {"$abs"}
and isinstance(d["$abs"], dict)) Try / catch
try:
rank = Rank.from_dict(rank_expr)
except (TypeError, ValueError) as e:
raise ValueError(f"invalid rank expression {rank_expr!r}: {e}") from e Prevention
- Unary operators ($abs/$exp/$log) take one bare rank dict — no list wrapping, no bare literals
- Wrap constants with $val before nesting: {"$abs": {"$val": 5}}
- Use abs(rank).to_dict() in Python instead of hand-writing the dict
When it happens
Trigger: Rank.from_dict({'$abs': 5}), {'$abs': [{'$val': 5}]}, or {'$abs': [knn_rank]} — any non-dict payload, at any nesting depth in the expression tree.
Common situations: Wrapping the operand in brackets 'to be safe' because list operators ($sum/$mul) take lists; passing a literal number directly; hand-authored JSON that abbreviates {'$val': 5} to 5.
Related errors
- $sub requires a dict with 'left' and 'right', got {type(sub_
- $mul requires a list, got {type(ranks_data).__name__}
- $div requires a dict with 'left' and 'right', got {type(div_
- $exp requires a rank dict, got {type(child_data).__name__}
- $log requires a rank dict, got {type(child_data).__name__}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/982684555a51b03b.
Report an issue: GitHub.