{"record":{"id":"ac331b0bb0dcaf14","repo":"HKUDS/Vibe-Trading","slug":"legs-index-premium-must-be-numeric-or-null","errorCode":null,"errorMessage":"legs[{index}].premium must be numeric or null","messagePattern":"legs\\[(.+?)\\]\\.premium must be numeric or null","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/options_payoff_tool.py","lineNumber":253,"sourceCode":"    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)\n        except (TypeError, ValueError, OverflowError) as exc:\n            raise ValueError(f\"legs[{index}].premium must be numeric or null\") from exc\n        legs.append(OptionLeg(option_type, strike, qty, premium))\n    return legs\n\n\ndef _required_float(kwargs: dict[str, Any], name: str) -> float:\n    \"\"\"Read a required finite float.\"\"\"\n    if name not in kwargs or kwargs[name] is None or kwargs[name] == \"\":\n        raise ValueError(f\"{name} is required\")\n    try:\n        value = float(kwargs[name])\n    except (TypeError, ValueError, OverflowError) as exc:\n        raise ValueError(f\"{name} must be numeric\") from exc\n    if not math.isfinite(value):\n        raise ValueError(f\"{name} must be finite\")\n    return value\n\n\ndef _optional_float(kwargs: dict[str, Any], name: str, default: float) -> float:","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/options_payoff_tool.py#L235-L271","documentation":"Thrown when a leg's optional premium field is present but cannot be converted to float (string garbage, list, dict, bool-adjacent overflow). premium may be null/omitted to let the tool default it, but any present value must be numeric.","triggerScenarios":"premium=\"2.5bp\", premium=[2.5], premium={\"value\":2.5}, premium=float('inf') from parsed JSON 'Infinity'.","commonSituations":"Premiums imported from broker CSVs with text like '2.50 x' or '—'; LLM hallucinating structured premium objects; spreadsheets returning strings.","solutions":["Coerce premium to a plain number or set it to null","Parse broker text: float(re.sub(r'[^0-9.\\-]', '', raw)) with a guard","Omit the premium key entirely when unknown"],"exampleFix":"// before\n{\"option_type\": \"call\", \"strike\": 100, \"qty\": 1, \"premium\": \"2.50 x\"}\n// after\n{\"option_type\": \"call\", \"strike\": 100, \"qty\": 1, \"premium\": 2.50}","handlingStrategy":"validation","validationCode":"for leg in legs:\n    p = leg.get(\"premium\")\n    if p is not None:\n        try: float(p)\n        except (TypeError, ValueError, OverflowError): leg[\"premium\"] = None  # or hard-fail","typeGuard":"def premium_ok(leg: dict) -> bool:\n    p = leg.get(\"premium\")\n    if p is None: return True\n    try: float(p); return True\n    except (TypeError, ValueError, OverflowError): return False","tryCatchPattern":"try:\n    execute(kwargs)\nexcept ValueError as e:\n    if \"premium must be numeric\" in str(e):\n        strip_premiums_and_retry(kwargs)","preventionTips":["Treat unparseable premiums as null/omitted, not text","Clean broker CSV premium columns at import time","Keep premium as number in your data model"],"tags":["validation","options","type-coercion"],"backgroundTag":"numeric-field-invalid","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}