{"record":{"id":"c5ca413f0d928168","repo":"HKUDS/Vibe-Trading","slug":"legs-may-contain-at-most-max-legs-entries","errorCode":null,"errorMessage":"legs may contain at most {_MAX_LEGS} entries","messagePattern":"legs may contain at most (.+?) entries","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/options_payoff_tool.py","lineNumber":233,"sourceCode":"                \"iv_values\": _rounded_array(iv_values),\n                \"spot\": _rounded_array(report.spot_grid),\n                \"pnl\": [_rounded_array(row) for row in np.asarray(scenarios, dtype=float)],\n            },\n            \"limitations\": [\n                \"European Black-Scholes marks with constant rate and volatility per scenario.\",\n                \"No dividends, early exercise, assignment, slippage, or margin model.\",\n                \"Scenario P&L is mark-to-market and does not deduct a hypothetical exit commission.\",\n            ],\n        }\n        return json.dumps(payload, ensure_ascii=False, allow_nan=False)\n\n\ndef _coerce_legs(raw: Any) -> list[OptionLeg]:\n    \"\"\"Parse and validate raw JSON-style leg objects.\"\"\"\n    if not isinstance(raw, list) or not raw:\n        raise ValueError(\"legs must be a non-empty array\")\n    if len(raw) > _MAX_LEGS:\n        raise ValueError(f\"legs may contain at most {_MAX_LEGS} entries\")\n\n    legs: list[OptionLeg] = []\n    for index, item in enumerate(raw):\n        if not isinstance(item, dict):\n            raise ValueError(f\"legs[{index}] must be an object\")\n        option_type = str(item.get(\"option_type\") or \"\").strip().lower()\n        try:\n            strike = float(item[\"strike\"])\n            raw_qty = item[\"qty\"]\n            qty_number = float(raw_qty)\n        except (KeyError, TypeError, ValueError, OverflowError) as exc:\n            raise ValueError(f\"legs[{index}] has invalid strike or qty: {exc}\") from exc\n        if isinstance(raw_qty, bool) or not qty_number.is_integer():\n            raise ValueError(f\"legs[{index}].qty must be a non-zero integer\")\n        qty = int(qty_number)\n        raw_premium = item.get(\"premium\")\n        try:\n            premium = None if raw_premium is None else float(raw_premium)","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/options_payoff_tool.py#L215-L251","documentation":"Thrown by _coerce_legs when the legs array exceeds _MAX_LEGS entries. The tool caps portfolio size to bound compute and output size for payoff/greeks calculation. It fires after the non-empty check, before per-leg parsing.","triggerScenarios":"Calling execute/_portfolio_greeks with more than _MAX_LEGS leg objects (e.g. programmatically generated spreads, iron condors plus hedges, or batch portfolios).","commonSituations":"Scripts that synthesize many strikes for a strategy sweep; users pasting a whole position file into the tool; LLMs generating oversized illustrative portfolios.","solutions":["Split the portfolio into multiple calls, each within the limit","Filter to only the significant legs (non-zero qty) before sending","Check _MAX_LEGS at the top of options_payoff_tool.py and stay under it"],"exampleFix":"// before\nlegs = build_all_50_legs(positions)\nresult = execute({\"legs\": legs, ...})\n// after\nlegs = build_all_50_legs(positions)\nfor chunk in [legs[i:i+_MAX_LEGS] for i in range(0, len(legs), _MAX_LEGS)]:\n    result = execute({\"legs\": chunk, ...})","handlingStrategy":"validation","validationCode":"from agent.src.tools.options_payoff_tool import _MAX_LEGS\nif len(legs) > _MAX_LEGS:\n    legs = legs[:_MAX_LEGS]  # or split into chunks","typeGuard":"def within_leg_limit(legs: list) -> bool:\n    return 0 < len(legs) <= _MAX_LEGS","tryCatchPattern":"try:\n    execute(kwargs)\nexcept ValueError as e:\n    if \"at most\" in str(e):\n        results = [execute({**kwargs, \"legs\": c}) for c in chunks(legs, _MAX_LEGS)]","preventionTips":["Read _MAX_LEGS from the module rather than hardcoding","Chunk large portfolios programmatically","Filter zero-qty legs before sending"],"tags":["validation","options","limits"],"backgroundTag":"input-limit-exceeded","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}