HKUDS/Vibe-Trading · error · ValueError
{field_name} must be a string, got {type(value).__name__}
Error message
{field_name} must be a string, got {type(value).__name__} What it means
normalize_currency (and thus EntityRate/EntityLevel __post_init__ and get_rate) requires currency codes to be str; passing any other type raises ValueError naming the field and the offending type.
Source
Thrown at agent/src/entities/models.py:86
def normalize_currency(value: str, *, field_name: str = "currency") -> str:
"""Normalize a currency code to its canonical uppercase form.
Codes are upper-cased and stripped. Length is deliberately not constrained
to three characters: this project also handles crypto quote assets such as
``USDT``, and rejecting them would push callers into faking a code.
Args:
value: Raw currency code, e.g. ``" usd "``.
field_name: Name used in the error message, for caller context.
Returns:
The canonical code, e.g. ``"USD"``.
Raises:
ValueError: If the code is empty, not a string, or contains whitespace.
"""
if not isinstance(value, str):
raise ValueError(f"{field_name} must be a string, got {type(value).__name__}")
cleaned = value.strip().upper()
if not cleaned:
raise ValueError(f"{field_name} is required and cannot be empty")
if any(ch.isspace() for ch in cleaned):
raise ValueError(f"{field_name} cannot contain whitespace, got {value!r}")
return cleaned
def normalize_date(value: date | datetime | str, *, field_name: str = "date") -> date:
"""Coerce a supported date input to a plain ``datetime.date``.
``datetime`` instances are truncated to their date, because a cash flow
settles on a day, not at a timestamp; keeping the time component would make
two flows on the same day compare unequal for no economic reason.
Strings must be ISO-8601 (``YYYY-MM-DD``, optionally with a time part).
Ambiguous regional formats such as ``03/04/2024`` are rejected rather than
guessed, since guessing day-first vs month-first is a silent wrong answer.View on GitHub (pinned to 80ffdda44c)
Solutions
- Ensure a str currency code is supplied ('USD'); guard optional values before construction
- Default None to a known code: currency or 'USD' at the call site
- Validate external data with a schema/parse step before building models
Example fix
# before
rate = EntityRate(currency=None, ...)
# after
rate = EntityRate(currency=data.get('currency') or 'USD', ...) Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(ccy, str): ccy = 'USD' # or raise early with context
Type guard
def is_currency_str(v) -> bool: return isinstance(v, str) and bool(v.strip())
Try / catch
except ValueError as e:
if 'must be a string' in str(e): coerce/repair the field and retry Prevention
- Type-check external data at the boundary
- Coalesce None to a default code
When it happens
Trigger: Passing None, bytes, or a non-str object to currency= of entities models, e.g. Money(currency=None) or a value pulled from an untyped dict/JSON.
Common situations: Optional fields from APIs defaulting to None, or reading currency codes from JSON where null sneaks in.
Related errors
- {field_name} is required and cannot be empty
- {field_name} cannot contain whitespace, got {value!r}
- {field_name} must be a date, datetime, or ISO-8601 string, g
- pre_translated=True asserts the flows were already converted
- entity_id is required and cannot be empty
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/f935157ba9e67feb.
Report an issue: GitHub.