HKUDS/Vibe-Trading · error · ValueError

{name} must be an integer, got {value!r}

Error message

{name} must be an integer, got {value!r}

What it means

strategy_discovery_tool._coerce_int rejects values that are not coercible to int. bools are rejected explicitly (True/False would otherwise pass as 1/0 since bool subclasses int), and this branch is the bool check: any boolean value for an integer parameter raises immediately. The message names the parameter and shows the offending value.

Source

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

def _envelope(result: Any) -> str:
    """Serialize a facade envelope defensively.

    The facade contract returns ``{"status": "ok", ...}`` or
    ``{"status": "error", "error": ...}`` dicts; anything else is wrapped
    so the agent always receives parseable JSON.
    """
    if not isinstance(result, dict):
        result = {"status": "ok", "result": result}
    return json.dumps(result, ensure_ascii=False)


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}")

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass an actual integer (e.g. 10) instead of a boolean
  2. If the boolean came from a schema mismatch, fix the tool-call schema so the field is typed integer
  3. For optional params, pass None to get the default instead of True/False

Example fix

# before
tool.execute(top_n=True)
# after
tool.execute(top_n=10)
Defensive patterns

Strategy: type-guard

Validate before calling

assert not isinstance(value, bool), f"{name} must be int, not bool"
tool.execute(**{name: value})

Type guard

def is_int_arg(v) -> bool:
    return not isinstance(v, bool) and (
        isinstance(v, int) or (isinstance(v, str) and v.strip().lstrip("+-").isdigit())
    )

Prevention

When it happens

Trigger: Passing True/False for an int parameter, e.g. execute(limit=True) or limit=False; JSON tool args where the model emitted a boolean for a numeric field.

Common situations: LLM tool-call schemas mapping "top_n" to a checkbox-like boolean; upstream code passing flags into count parameters; Python truthiness habits like passing `if x else 0` results that yield True.

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/7d0bf51194e28e90. Report an issue: GitHub.