HKUDS/Vibe-Trading · error · ValueError
waterfall does not reconcile on {label}: tiers give {compute
Error message
waterfall does not reconcile on {label}: tiers give {computed!r}, expected {expected!r} What it means
The waterfall-level reconciliation check in __post_init__ verifies that summing tiers for each reconciled label (e.g. contributed capital, distributions, carry) matches the expected totals supplied by the caller. A mismatch means the tier breakdown disagrees with the waterfall inputs.
Source
Thrown at agent/src/quantlib/fundmath.py:1087
Raises:
ValueError: If the tier amounts do not sum to ``distributable``, or
if the per-side totals do not match the tier splits.
"""
checks = (
("distributable", sum(tier.amount for tier in self.tiers), self.distributable),
("lp_total", sum(tier.lp_amount for tier in self.tiers), self.lp_total),
("gp_total", sum(tier.gp_amount for tier in self.tiers), self.gp_total),
("lp+gp", self.lp_total + self.gp_total, self.distributable),
)
for label, computed, expected in checks:
if not math.isclose(
computed,
expected,
rel_tol=_ALLOCATION_TOLERANCE,
abs_tol=_ALLOCATION_TOLERANCE,
):
raise ValueError(
f"waterfall does not reconcile on {label}: tiers give "
f"{computed!r}, expected {expected!r}"
)
def tier_amount(self, name: str) -> float:
"""Dollars that flowed through a named tier.
Args:
name: One of the ``TIER_*`` constants.
Returns:
The tier's ``amount``, or ``0.0`` if that tier is absent.
"""
for tier in self.tiers:
if tier.name == name:
return tier.amount
return 0.0
View on GitHub (pinned to 80ffdda44c)
Solutions
- Recompute expected totals from the same numbers used to build the tiers (single source of truth)
- Round both tiers and expected totals to the same decimal precision before constructing the waterfall
- Rebuild the entire waterfall from current inputs instead of reusing tier objects
Example fix
# before tiers = split_tiers(cash, r=0.2) # full precision wf = Waterfall(tiers=tiers, contributed=round(paid_in, 2)) # mismatch -> raises # after tiers = [round_tier(t) for t in split_tiers(cash, r=0.2)] wf = Waterfall(tiers=tiers, contributed=round(paid_in, 2))
Defensive patterns
Strategy: validation
Validate before calling
computed = sum(t.lp_amount + t.gp_amount for t in tiers) assert math.isclose(computed, expected, rel_tol=1e-9, abs_tol=1e-9)
Prevention
- Compute expected totals from the same intermediate values as the tiers
- Rebuild waterfalls from scratch rather than reusing tier objects
When it happens
Trigger: Building a WaterfallResult where tiers were constructed from stale or differently-rounded inputs than the expected totals passed alongside them, so computed != expected beyond _ALLOCATION_TOLERANCE.
Common situations: Mixing tiers computed at full precision with expected totals rounded to cents; reusing tiers from a previous run after inputs changed; partial-distribution logic that fills tiers inconsistently with totals.
Related errors
- tier {self.name!r} has a negative {label} of {value!r}
- tier {self.name!r} does not conserve cash: lp {self.lp_amoun
- {label} must be non-negative, got {value!r}
- carry_rate must be in [0, 1), got {carry_rate!r}
- catch_up_rate must be in [0, 1], got {catch_up_rate!r}
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/232bcdcd1e92dbb9.
Report an issue: GitHub.