HKUDS/Vibe-Trading · error · ValueError

legs[ ] has invalid strike or qty

Error message

legs[{index}] has invalid strike or qty: {exc}

What it means

Thrown when a leg's strike or qty fails numeric conversion — the key is missing (KeyError), the value is a non-numeric string/list (TypeError/ValueError), or an enormous number overflows float conversion. The chained exception message carries the underlying conversion error.

Solutions

  1. Ensure both strike and qty are present and numeric (strings like "100.5" are fine)
  2. Strip currency/separator formatting before passing: float(raw.replace(',',''))
  3. If fields come from user input, coerce and validate them in your own schema first

Example fix

// before
{"option_type": "call", "strike": "100 USD", "qty": "1"}
// after
{"option_type": "call", "strike": 100.0, "qty": 1}
Defensive patterns

Strategy: validation

Validate before calling

for leg in legs:
    for k in ("strike", "qty"):
        try:
            float(leg[k])
        except (KeyError, TypeError, ValueError):
            raise ValueError(f"leg field {k} missing/non-numeric: {leg}")

Type guard

def leg_numerics_ok(leg: dict) -> bool:
    try:
        float(leg["strike"]); float(leg["qty"])
        return True
    except (KeyError, TypeError, ValueError, OverflowError):
        return False

Try / catch

try:
    execute(kwargs)
except ValueError as e:
    if "invalid strike or qty" in str(e):
        highlight_bad_leg_to_user(e)

Prevention

When it happens

Trigger: leg missing the strike or qty key; strike="abc"; qty=[1]; qty=1e400 in raw text; qty=None. e.g. {"option_type":"call","strike":100} (no qty) triggers it.

Common situations: Handwritten JSON with typos or omitted fields; LLM-generated legs that drop qty; string numbers with currency symbols or commas ("1,000").

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/0be49f32aaf4af16. Report an issue: GitHub.

Appendix: source

Thrown at agent/src/tools/options_payoff_tool.py:245

def _coerce_legs(raw: Any) -> list[OptionLeg]:
    """Parse and validate raw JSON-style leg objects."""
    if not isinstance(raw, list) or not raw:
        raise ValueError("legs must be a non-empty array")
    if len(raw) > _MAX_LEGS:
        raise ValueError(f"legs may contain at most {_MAX_LEGS} entries")

    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])

View on GitHub (pinned to 80ffdda44c)