HKUDS/Vibe-Trading · error · ValueError

{name} must be a number, got {value!r}

Error message

{name} must be a number, got {value!r}

What it means

strategy_discovery_tool._coerce_opt_float validates optional numeric parameters. It first rejects booleans: since bool is not a valid numeric type for this tool, passing True/False for a float parameter raises ValueError naming the parameter. NaN/inf are rejected later in a separate check.

Source

Thrown at agent/src/tools/strategy_discovery_tool.py:86

def _coerce_int(value: Any, name: str, default: int) -> int:
    """Coerce an integer parameter; raise ``ValueError`` on bad input."""
    if value is None:
        return default
    if isinstance(value, bool):  # bool is an int subclass — reject explicitly
        raise ValueError(f"{name} must be an integer, got {value!r}")
    try:
        return int(value)
    except (TypeError, ValueError, OverflowError) as exc:
        raise ValueError(f"{name} must be an integer, got {value!r}") from exc


def _coerce_opt_float(value: Any, name: str) -> float | None:
    """Coerce an optional numeric parameter; reject NaN/inf and bad types."""
    if value is None:
        return None
    if isinstance(value, bool):
        raise ValueError(f"{name} must be a number, got {value!r}")
    try:
        result = float(value)
    except (TypeError, ValueError, OverflowError) as exc:
        raise ValueError(f"{name} must be a number, got {value!r}") from exc
    if result != result or result in (float("inf"), float("-inf")):
        raise ValueError(f"{name} must be a finite number, got {value!r}")
    return result


def _coerce_opt_str(value: Any, name: str) -> str | None:
    """Coerce an optional string parameter; blank/None become ``None``."""
    if value is None:
        return None
    if not isinstance(value, str):
        raise ValueError(f"{name} must be a string, got {value!r}")
    if len(value) > _MAX_STRING_PARAM_CHARS:
        raise ValueError(
            f"{name} is too long ({len(value)} chars; "

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass a real number (e.g. 0.5) or None to omit
  2. Fix the calling schema/typing so the field is number|nullable, not boolean
  3. Audit upstream serialization that may coerce 0/1 to false/true (e.g. some JSON Schema validators)

Example fix

# before
tool.execute(min_sharpe=True)
# after
tool.execute(min_sharpe=1.0)
Defensive patterns

Strategy: type-guard

Validate before calling

if value is not None and isinstance(value, bool):
    raise ValueError(f"{name} must be a number, not a boolean")
tool.execute(**{name: value})

Type guard

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

Prevention

When it happens

Trigger: Passing True or False for an optional numeric parameter, e.g. execute(min_sharpe=True); model-emitted JSON with a boolean in a number field.

Common situations: LLM tool-call schemas confusing numeric thresholds with flags; truthy shorthand like passing `use_filter and 0.5` which evaluates to a bool; UI toggles wired to numeric inputs.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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