{"record":{"id":"5771d5ac2187c459","repo":"HKUDS/Vibe-Trading","slug":"catch-up-rate-catch-up-rate-r-must-exceed-carry","errorCode":null,"errorMessage":"catch_up_rate={catch_up_rate!r} must exceed carry_rate={carry_rate!r}, otherwise the catch-up tier can never complete. Pass catch_up_rate=0.0 for a fund with no catch-up.","messagePattern":"catch_up_rate=(.+?) must exceed carry_rate=(.+?), otherwise the catch-up tier can never complete\\. Pass catch_up_rate=0\\.0 for a fund with no catch-up\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/fundmath.py","lineNumber":1179,"sourceCode":"\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:\n        catch_up_target = 0.0\n    catch_up = min(remaining, catch_up_target)","sourceCodeStart":1161,"sourceCodeEnd":1197,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/fundmath.py#L1161-L1197","documentation":"For the catch-up tier to ever complete, the GP's share during catch up (catch_up_rate) must strictly exceed the ongoing carry rate; otherwise the GP can never reach its carry level. If the fund has no catch-up, the API requires the explicit sentinel 0.0 to opt out.","triggerScenarios":"Calling waterfall_split(carry_rate=0.2, catch_up_rate=0.2) or catch_up_rate=0.15 < carry_rate with catch_up_rate > 0.","commonSituations":"Defaulting catch_up_rate to the same value as carry_rate 'for consistency'; misreading a term sheet where the 100% catch-up should be passed as 1.0.","solutions":["Pass catch_up_rate=0.0 for a fund with no catch-up tier","Pass a full catch-up as 1.0 (the common '100% catch-up' term)","Otherwise pass a rate strictly greater than carry_rate per the LPA"],"exampleFix":"# before\nwaterfall_split(..., carry_rate=0.2, catch_up_rate=0.2)\n\n# after\nwaterfall_split(..., carry_rate=0.2, catch_up_rate=0.0)  # no catch-up\n# or full catch-up:\nwaterfall_split(..., carry_rate=0.2, catch_up_rate=1.0)","handlingStrategy":"validation","validationCode":"if catch_up_rate > 0.0:\n    assert catch_up_rate > carry_rate, \"catch-up must exceed carry; use 0.0 to disable\"","typeGuard":"def catch_up_is_consistent(carry: float, catch_up: float) -> bool:\n    return catch_up == 0.0 or catch_up > carry","tryCatchPattern":null,"preventionTips":["Default catch_up_rate to 0.0, not to carry_rate","Map LPA '100% catch-up' to 1.0 explicitly"],"tags":["fund-math","waterfall","catch-up","carry","configuration"],"backgroundTag":"invalid-argument-relationship","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}