HKUDS/Vibe-Trading · error · ValueError
legs[{index}].premium must be numeric or null
Error message
legs[{index}].premium must be numeric or null What it means
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.
Source
Thrown at agent/src/tools/options_payoff_tool.py:253
legs: list[OptionLeg] = []
for index, item in enumerate(raw):
if not isinstance(item, dict):
raise ValueError(f"legs[{index}] must be an object")
option_type = str(item.get("option_type") or "").strip().lower()
try:
strike = float(item["strike"])
raw_qty = item["qty"]
qty_number = float(raw_qty)
except (KeyError, TypeError, ValueError, OverflowError) as exc:
raise ValueError(f"legs[{index}] has invalid strike or qty: {exc}") from exc
if isinstance(raw_qty, bool) or not qty_number.is_integer():
raise ValueError(f"legs[{index}].qty must be a non-zero integer")
qty = int(qty_number)
raw_premium = item.get("premium")
try:
premium = None if raw_premium is None else float(raw_premium)
except (TypeError, ValueError, OverflowError) as exc:
raise ValueError(f"legs[{index}].premium must be numeric or null") from exc
legs.append(OptionLeg(option_type, strike, qty, premium))
return legs
def _required_float(kwargs: dict[str, Any], name: str) -> float:
"""Read a required finite float."""
if name not in kwargs or kwargs[name] is None or kwargs[name] == "":
raise ValueError(f"{name} is required")
try:
value = float(kwargs[name])
except (TypeError, ValueError, OverflowError) as exc:
raise ValueError(f"{name} must be numeric") from exc
if not math.isfinite(value):
raise ValueError(f"{name} must be finite")
return value
def _optional_float(kwargs: dict[str, Any], name: str, default: float) -> float:View on GitHub (pinned to 80ffdda44c)
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
Example fix
// before
{"option_type": "call", "strike": 100, "qty": 1, "premium": "2.50 x"}
// after
{"option_type": "call", "strike": 100, "qty": 1, "premium": 2.50} Defensive patterns
Strategy: validation
Validate before calling
for leg in legs:
p = leg.get("premium")
if p is not None:
try: float(p)
except (TypeError, ValueError, OverflowError): leg["premium"] = None # or hard-fail Type guard
def premium_ok(leg: dict) -> bool:
p = leg.get("premium")
if p is None: return True
try: float(p); return True
except (TypeError, ValueError, OverflowError): return False Try / catch
try:
execute(kwargs)
except ValueError as e:
if "premium must be numeric" in str(e):
strip_premiums_and_retry(kwargs) Prevention
- Treat unparseable premiums as null/omitted, not text
- Clean broker CSV premium columns at import time
- Keep premium as number in your data model
When it happens
Trigger: premium="2.5bp", premium=[2.5], premium={"value":2.5}, premium=float('inf') from parsed JSON 'Infinity'.
Common situations: Premiums imported from broker CSVs with text like '2.50 x' or '—'; LLM hallucinating structured premium objects; spreadsheets returning strings.
Related errors
- legs[{index}] has invalid strike or qty: {exc}
- {name} must be numeric
- invalid period: {exc}
- T must be > 0 to imply a volatility, got {T}
- legs must be a non-empty array
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/ac331b0bb0dcaf14.
Report an issue: GitHub.