{"record":{"id":"5dd61c9cc94669e6","repo":"OpenBB-finance/OpenBB","slug":"port-code-must-be-a-string-or-a-list-of-strings","errorCode":null,"errorMessage":"port_code must be a string or a list of strings.","messagePattern":"port_code must be a string or a list of strings\\.","errorType":"validation","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/imf/openbb_imf/models/port_volume.py","lineNumber":83,"sourceCode":"        description=\"Port code to filter results by a specific port.\"\n        + \" This parameter is ignored if `country` parameter is provided.\"\n        + \" To get a list of available ports, use `obb.economy.shipping.port_info()`.\",\n    )\n    country: PortCountries | None = Field(\n        default=None,\n        description=\"Country to focus on. Enter as a 3-letter ISO country code.\"\n        + \" This parameter is overridden by `port_code` if both are provided.\",\n    )\n\n    @field_validator(\"port_code\")\n    @classmethod\n    def validate_port_code(cls, v):\n        \"\"\"Validate port_code.\"\"\"\n        if isinstance(v, str):\n            v = [v] if \",\" not in v else v.split(\",\")\n\n        if not isinstance(v, list) or not all(isinstance(item, str) for item in v):\n            raise OpenBBError(\"port_code must be a string or a list of strings.\")\n\n        port_id_choices = get_port_id_choices()\n        port_id_map = {\n            choice[\"value\"].lower(): choice[\"label\"] for choice in port_id_choices\n        }\n\n        # Create country name to ISO code mapping\n        country_name_to_iso = {}\n        for iso_code, country_name in PORT_COUNTRIES.items():\n            country_name_to_iso[country_name.lower()] = iso_code\n            country_name_to_iso[country_name.lower().replace(\" \", \"_\")] = iso_code\n\n        new_values: list = []\n        for item in v:\n            if item == \"all\":\n                return \"all\"\n\n            # Try direct ISO country code lookup first","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/imf/openbb_imf/models/port_volume.py#L65-L101","documentation":"Field validator on `port_code` in the port_volume query params: after normalizing a string (single value or comma-split) to a list, the value must be a list of strings. Non-string items (ints, floats, None mixed in) or a non-list/non-string input type (dict, int) raise this before any port-id resolution happens.","triggerScenarios":"Passing `port_code=12345` (numeric port id), `port_code=[12345, 'usnyc']` with numeric elements, or a dict/other object. A plain string or list of strings passes this stage and moves on to name/id matching.","commonSituations":"Upstream data pipelines supplying port ids as integers from a database; JSON configs where numbers are not quoted; pandas cells yielding numpy ints.","solutions":["Pass port codes as strings: `port_code='port12345'` or `port_code=['port12345','usnyc']`.","Map numeric inputs with str() before building the query.","Validate the shape (list[str]) at your API boundary before calling."],"exampleFix":"# before\nport_volume(port_code=[37972, 'usnyc'])\n\n# after\nport_volume(port_code=['37972', 'usnyc'])","handlingStrategy":"type-guard","validationCode":"if isinstance(port_code, str):\n    port_code = [p.strip() for p in port_code.split(',')] if ',' in port_code else [port_code]\nif not isinstance(port_code, list) or not all(isinstance(p, str) for p in port_code):\n    port_code = [str(p) for p in port_code]  # or reject at your boundary","typeGuard":"def is_port_code_input(v) -> bool:\n    if isinstance(v, str):\n        return True\n    return isinstance(v, list) and all(isinstance(x, str) for x in v)","tryCatchPattern":null,"preventionTips":["Quote numeric ids in JSON configs","Coerce DB/pandas numeric port ids with str() before calling"],"tags":["imf","portwatch","validation","type-error","port-code"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}