{"record":{"id":"275fb66c98303b73","repo":"HKUDS/Vibe-Trading","slug":"name-must-be-a-string-got-value-r","errorCode":null,"errorMessage":"{name} must be a string, got {value!r}","messagePattern":"(.+?) must be a string, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/strategy_discovery_tool.py","lineNumber":101,"sourceCode":"    if value is None:\n        return None\n    if isinstance(value, bool):\n        raise ValueError(f\"{name} must be a number, got {value!r}\")\n    try:\n        result = float(value)\n    except (TypeError, ValueError, OverflowError) as exc:\n        raise ValueError(f\"{name} must be a number, got {value!r}\") from exc\n    if result != result or result in (float(\"inf\"), float(\"-inf\")):\n        raise ValueError(f\"{name} must be a finite number, got {value!r}\")\n    return result\n\n\ndef _coerce_opt_str(value: Any, name: str) -> str | None:\n    \"\"\"Coerce an optional string parameter; blank/None become ``None``.\"\"\"\n    if value is None:\n        return None\n    if not isinstance(value, str):\n        raise ValueError(f\"{name} must be a string, got {value!r}\")\n    if len(value) > _MAX_STRING_PARAM_CHARS:\n        raise ValueError(\n            f\"{name} is too long ({len(value)} chars; \"\n            f\"max {_MAX_STRING_PARAM_CHARS})\"\n        )\n    text = value.strip()\n    return text or None\n\n\ndef _coerce_bool(value: Any, name: str, default: bool) -> bool:\n    \"\"\"Coerce a boolean parameter, tolerating common LLM string forms.\"\"\"\n    if value is None:\n        return default\n    if isinstance(value, bool):\n        return value\n    if isinstance(value, str):\n        lowered = value.strip().lower()\n        if lowered in {\"true\", \"1\", \"yes\"}:","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/strategy_discovery_tool.py#L83-L119","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before\ntool.execute(universe=['SPY','QQQ'])\n# after\ntool.execute(universe=\"SPY,QQQ\")  # or the documented string format","handlingStrategy":"type-guard","validationCode":"if value is not None and not isinstance(value, str):\n    value = str(value)\ntool.execute(**{name: value})","typeGuard":"def is_str_arg(v) -> bool:\n    return v is None or isinstance(v, str)","tryCatchPattern":null,"preventionTips":["Convert ints/IDs to str explicitly before tool calls","Keep string params as strings in JSON schemas (no implicit coercion)"],"tags":["strategy-discovery","type-coercion","string-args","validation"],"backgroundTag":"invalid-argument-type","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}