HKUDS/Vibe-Trading · error · ValueError
{name} must be a string, got {value!r}
Error message
{name} must be a string, got {value!r} What it means
strategy_discovery_tool._coerce_opt_str validates optional string parameters and requires them to actually be str instances — no implicit str() conversion is performed. Passing any non-string, non-None value (int, list, dict, bool) raises ValueError naming the parameter and the value. Empty/None are handled separately as absent.
Source
Thrown at agent/src/tools/strategy_discovery_tool.py:101
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; "
f"max {_MAX_STRING_PARAM_CHARS})"
)
text = value.strip()
return text or None
def _coerce_bool(value: Any, name: str, default: bool) -> bool:
"""Coerce a boolean parameter, tolerating common LLM string forms."""
if value is None:
return default
if isinstance(value, bool):
return value
if isinstance(value, str):
lowered = value.strip().lower()
if lowered in {"true", "1", "yes"}:View on GitHub (pinned to 80ffdda44c)
Solutions
- Convert the value to str yourself before passing: str(value) when appropriate
- Pass the correctly typed value (e.g. a string name, not a list)
- Omit the kwarg or pass None if the optional string isn't needed
Example fix
# before tool.execute(universe=['SPY','QQQ']) # after tool.execute(universe="SPY,QQQ") # or the documented string format
Defensive patterns
Strategy: type-guard
Validate before calling
if value is not None and not isinstance(value, str):
value = str(value)
tool.execute(**{name: value}) Type guard
def is_str_arg(v) -> bool:
return v is None or isinstance(v, str) Prevention
- Convert ints/IDs to str explicitly before tool calls
- Keep string params as strings in JSON schemas (no implicit coercion)
When it happens
Trigger: Passing 123, ["a"], or True for a string parameter, e.g. execute(universe=500) where a ticker list string is expected; passing bytes is also rejected (not a str).
Common situations: LLM tool calls emitting JSON numbers/arrays for text fields; upstream code passing IDs as ints where the tool wants strings; bytes vs str confusion after deserialization.
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
- {name} must be an integer, got {value!r}
- {name} must be a number, got {value!r}
- {name} is too long ({len(value)} chars; max {_MAX_STRING_PAR
- {name} must be a boolean, got {value!r}
- invalid period: {exc}
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/275fb66c98303b73.
Report an issue: GitHub.