{"record":{"id":"f935157ba9e67feb","repo":"HKUDS/Vibe-Trading","slug":"field-name-must-be-a-string-got-type-value","errorCode":null,"errorMessage":"{field_name} must be a string, got {type(value).__name__}","messagePattern":"(.+?) must be a string, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/entities/models.py","lineNumber":86,"sourceCode":"def normalize_currency(value: str, *, field_name: str = \"currency\") -> str:\n    \"\"\"Normalize a currency code to its canonical uppercase form.\n\n    Codes are upper-cased and stripped. Length is deliberately not constrained\n    to three characters: this project also handles crypto quote assets such as\n    ``USDT``, and rejecting them would push callers into faking a code.\n\n    Args:\n        value: Raw currency code, e.g. ``\" usd \"``.\n        field_name: Name used in the error message, for caller context.\n\n    Returns:\n        The canonical code, e.g. ``\"USD\"``.\n\n    Raises:\n        ValueError: If the code is empty, not a string, or contains whitespace.\n    \"\"\"\n    if not isinstance(value, str):\n        raise ValueError(f\"{field_name} must be a string, got {type(value).__name__}\")\n    cleaned = value.strip().upper()\n    if not cleaned:\n        raise ValueError(f\"{field_name} is required and cannot be empty\")\n    if any(ch.isspace() for ch in cleaned):\n        raise ValueError(f\"{field_name} cannot contain whitespace, got {value!r}\")\n    return cleaned\n\n\ndef normalize_date(value: date | datetime | str, *, field_name: str = \"date\") -> date:\n    \"\"\"Coerce a supported date input to a plain ``datetime.date``.\n\n    ``datetime`` instances are truncated to their date, because a cash flow\n    settles on a day, not at a timestamp; keeping the time component would make\n    two flows on the same day compare unequal for no economic reason.\n\n    Strings must be ISO-8601 (``YYYY-MM-DD``, optionally with a time part).\n    Ambiguous regional formats such as ``03/04/2024`` are rejected rather than\n    guessed, since guessing day-first vs month-first is a silent wrong answer.","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/entities/models.py#L68-L104","documentation":"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.","triggerScenarios":"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.","commonSituations":"Optional fields from APIs defaulting to None, or reading currency codes from JSON where null sneaks in.","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"],"exampleFix":"# before\nrate = EntityRate(currency=None, ...)\n# after\nrate = EntityRate(currency=data.get('currency') or 'USD', ...)","handlingStrategy":"type-guard","validationCode":"if not isinstance(ccy, str): ccy = 'USD'  # or raise early with context","typeGuard":"def is_currency_str(v) -> bool: return isinstance(v, str) and bool(v.strip())","tryCatchPattern":"except ValueError as e:\n    if 'must be a string' in str(e): coerce/repair the field and retry","preventionTips":["Type-check external data at the boundary","Coalesce None to a default code"],"tags":["validation","type-error","currency","models"],"backgroundTag":"type-validation-failed","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}