{"record":{"id":"8a66ba47fa0e4713","repo":"HKUDS/Vibe-Trading","slug":"kind-must-be-a-string-got-type-value-name","errorCode":null,"errorMessage":"kind must be a string, got {type(value).__name__}","messagePattern":"kind must be a string, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/entities/cashflow.py","lineNumber":112,"sourceCode":"def normalize_kind(value: str) -> str:\n    \"\"\"Normalize a cash-flow kind label to its canonical snake_case form.\n\n    Real files spell the same concept as ``\"Capital Call\"``, ``\"capital-call\"``,\n    or ``\"CAPITAL_CALL\"``. Normalizing means the sign check in ``KIND_DIRECTION``\n    actually bites on those files instead of silently treating each spelling as\n    an unconstrained custom kind.\n\n    Args:\n        value: Raw kind label from a caller or a file.\n\n    Returns:\n        Lower-cased label with spaces and hyphens collapsed to underscores.\n\n    Raises:\n        ValueError: If the label is not a string or is blank.\n    \"\"\"\n    if not isinstance(value, str):\n        raise ValueError(f\"kind must be a string, got {type(value).__name__}\")\n    cleaned = value.strip().lower().replace(\"-\", \"_\").replace(\" \", \"_\")\n    while \"__\" in cleaned:\n        cleaned = cleaned.replace(\"__\", \"_\")\n    if not cleaned:\n        raise ValueError(\"kind is required and cannot be empty\")\n    return cleaned\n\n\n@dataclass(frozen=True)\nclass CashFlow:\n    \"\"\"A single dated cash amount in one currency.\n\n    Attributes:\n        date: Settlement date. ``datetime`` and ISO-8601 strings are accepted\n            and normalized to ``datetime.date``.\n        amount: Signed amount, positive into the holder. See the module\n            docstring for the convention and its enforcement.\n        kind: Canonical kind label, e.g. ``\"capital_call\"`` or ``\"coupon\"``.","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/entities/cashflow.py#L94-L130","documentation":"Raised by CashFlow normalize_kind when the kind argument is not a str instance (e.g. int, None, bytes). The kind label is normalized (lowercased, hyphens/spaces to underscores) and stored as a dataclass field, so non-string input fails fast in __post_init__ or the filter/external_flows helpers.","triggerScenarios":"Constructing a CashFlow-like entity or calling filter/external_flows with kind=42, kind=None, or bytes from un-decoded JSON input.","commonSituations":"Feeding raw JSON/YAML values where kind came back as a number or null; dynamic dicts built from spreadsheets where the column parses as int.","solutions":["Coerce kind to str before constructing: kind=str(value) if appropriate.","Validate upstream data shapes (e.g. JSON schema) so kind is always a string.","Check for None from optional mappings and supply a default label."],"exampleFix":"# before\nnormalize_kind(123)\n\n# after\nnormalize_kind(str(123))","handlingStrategy":"type-guard","validationCode":"def kind_is_str(value) -> bool:\n    return isinstance(value, str)","typeGuard":"def is_kind_string(value) -> bool:\n    return isinstance(value, str)","tryCatchPattern":"try:\n    flow = CashFlow(kind=raw_kind, ...)\nexcept ValueError as e:\n    if 'kind must be a string' in str(e):\n        raise TypeError(f'kind must come from string fields, got {raw_kind!r}') from e\n    raise","preventionTips":["Validate incoming records with a schema (pydantic/jsonschema) before entity construction","Coerce numeric labels to str explicitly at ingestion"],"tags":["cashflow","type-validation","entities"],"backgroundTag":"type-validation-error","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}