HKUDS/Vibe-Trading · error · ValueError

spot_points must be an integer

Error message

spot_points must be an integer

What it means

Thrown by _spot_points when the display-grid size parameter is a Python bool. Because bool subclasses int and float(True)==1.0 would pass numeric checks, the tool explicitly rejects booleans first. spot_points controls chart resolution and must be a whole number.

Source

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

    """Read an optional finite float, treating null and empty text as omitted."""
    raw = kwargs.get(name)
    if raw is None or raw == "":
        return default
    try:
        value = float(raw)
    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 _spot_points(raw: Any) -> int:
    """Validate the bounded display-grid size."""
    if raw is None or raw == "":
        return _DEFAULT_SPOT_POINTS
    if isinstance(raw, bool):
        raise ValueError("spot_points must be an integer")
    try:
        numeric = float(raw)
    except (TypeError, ValueError, OverflowError) as exc:
        raise ValueError("spot_points must be an integer") from exc
    if not math.isfinite(numeric) or not numeric.is_integer():
        raise ValueError("spot_points must be an integer")
    points = int(numeric)
    if not _MIN_SPOT_POINTS <= points <= _MAX_SPOT_POINTS:
        raise ValueError(f"spot_points must be between {_MIN_SPOT_POINTS} and {_MAX_SPOT_POINTS}")
    return points


def _spot_bounds(kwargs: dict[str, Any], legs: list[OptionLeg], entry_spot: float) -> tuple[float, float]:
    """Resolve explicit chart bounds or safe defaults covering every strike."""
    reference = [entry_spot, *(leg.strike for leg in legs)]
    default_min = max(min(reference) * 0.5, 0.0)
    default_max = max(reference) * 1.5
    spot_min = _optional_float(kwargs, "spot_min", default_min)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass an integer count like 50 or 200
  2. Rename/retype the config field that feeds spot_points
  3. Omit it to use _DEFAULT_SPOT_POINTS

Example fix

// before
execute({..., "spot_points": True})
// after
execute({..., "spot_points": 100})
Defensive patterns

Strategy: type-guard

Validate before calling

if isinstance(kwargs.get("spot_points"), bool):
    raise TypeError("spot_points must be an int, got bool")

Type guard

def spot_points_ok(v) -> bool:
    return v is None or (isinstance(v, int) and not isinstance(v, bool))

Try / catch

try:
    execute(kwargs)
except ValueError as e:
    if "spot_points" in str(e):
        kwargs.pop("spot_points", None); execute(kwargs)

Prevention

When it happens

Trigger: spot_points=True/False, typically from a config flag miswired into the parameter, or JSON true/false where a count was expected.

Common situations: Config schemas reusing a generic 'points' flag; LLM filling booleans into numeric slots; toggles accidentally bound to the wrong key.

Related errors


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