{"record":{"id":"ba6a208262b53137","repo":"HKUDS/Vibe-Trading","slug":"catch-up-rate-must-be-in-0-1-got-catch-up-rat","errorCode":null,"errorMessage":"catch_up_rate must be in [0, 1], got {catch_up_rate!r}","messagePattern":"catch_up_rate must be in \\[0, 1\\], got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/fundmath.py","lineNumber":1177,"sourceCode":"    Returns:\n        A :class:`WaterfallResult` whose tiers sum exactly to ``distributable``.\n\n    Raises:\n        ValueError: If any amount is negative, if ``carry_rate`` is outside\n            ``[0, 1)``, if ``catch_up_rate`` is outside ``[0, 1]``, or if a\n            non-zero ``catch_up_rate`` does not exceed ``carry_rate``.\n    \"\"\"\n    for label, value in (\n        (\"distributable\", distributable),\n        (\"contributed_capital\", contributed_capital),\n        (\"preferred_amount\", preferred_amount),\n    ):\n        if value < 0.0:\n            raise ValueError(f\"{label} must be non-negative, got {value!r}\")\n    if not 0.0 <= carry_rate < 1.0:\n        raise ValueError(f\"carry_rate must be in [0, 1), got {carry_rate!r}\")\n    if not 0.0 <= catch_up_rate <= 1.0:\n        raise ValueError(f\"catch_up_rate must be in [0, 1], got {catch_up_rate!r}\")\n    if catch_up_rate > 0.0 and catch_up_rate <= carry_rate:\n        raise ValueError(\n            f\"catch_up_rate={catch_up_rate!r} must exceed carry_rate=\"\n            f\"{carry_rate!r}, otherwise the catch-up tier can never complete. \"\n            \"Pass catch_up_rate=0.0 for a fund with no catch-up.\"\n        )\n\n    remaining = float(distributable)\n\n    return_of_capital = min(remaining, float(contributed_capital))\n    remaining -= return_of_capital\n\n    preferred_paid = min(remaining, float(preferred_amount))\n    remaining -= preferred_paid\n\n    if catch_up_rate > 0.0 and carry_rate > 0.0:\n        catch_up_target = carry_rate * preferred_paid / (catch_up_rate - carry_rate)\n    else:","sourceCodeStart":1159,"sourceCodeEnd":1195,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/fundmath.py#L1159-L1195","documentation":"The catch-up rate must be in [0, 1] — it is the fraction of catch-up tier dollars the GP receives during the catch-up phase. Values outside that range have no meaning in the tier math.","triggerScenarios":"Calling waterfall_split(catch_up_rate=1.5) or -0.1, e.g. passing 100 instead of 1.0 for a full catch-up.","commonSituations":"Percent-vs-fraction confusion (100 vs 1.0); copying a carry rate into the catch-up field with a different convention.","solutions":["Pass a fraction in [0,1]: 1.0 for full catch-up, 0.5 for 50%","Convert percentages at the boundary"],"exampleFix":"# before\nwaterfall_split(..., catch_up_rate=100)\n\n# after\nwaterfall_split(..., catch_up_rate=1.0)","handlingStrategy":"validation","validationCode":"assert 0.0 <= catch_up_rate <= 1.0, catch_up_rate","typeGuard":"def is_unit_interval(x: float) -> bool:\n    return isinstance(x, (int, float)) and 0.0 <= x <= 1.0","tryCatchPattern":null,"preventionTips":["Treat 1.0 as 'full catch-up', not 100","Centralize rate normalization from UI/config"],"tags":["fund-math","waterfall","catch-up-rate","percent-vs-fraction"],"backgroundTag":"invalid-argument-range","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}