{"record":{"id":"a931b03eefd6bbd5","repo":"OpenBB-finance/OpenBB","slug":"error-fetching-ports-data-e-e-args","errorCode":null,"errorMessage":"Error fetching ports data: {e} -> {e.args}","messagePattern":"Error fetching ports data: (.+?) -> (.+?)","errorType":"exception","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/imf/openbb_imf/utils/port_watch_helpers.py","lineNumber":429,"sourceCode":"    ports: list[dict] = []\n\n    try:\n        async with await get_async_requests_session() as session, await session.get(\n            url\n        ) as response:\n            if response.status != 200:\n                raise OpenBBError(\n                    f\"Failed to fetch ports data: {response.status} - {response.reason}\"\n                )\n            data = await response.json()\n\n            for feature in data.get(\"features\", []):\n                ports.append(feature.get(\"attributes\", {}))\n\n        return ports\n\n    except Exception as e:\n        raise OpenBBError(f\"Error fetching ports data: {e} -> {e.args}\") from e\n\n\ndef get_ports() -> list[dict[str, Any]]:\n    \"\"\"Get the list of all ports synchronously.\"\"\"\n    # pylint: disable=import-outside-toplevel\n    import asyncio\n\n    try:\n        loop = asyncio.get_running_loop()\n    except RuntimeError:\n        loop = None\n\n    if loop is not None:\n        # Already in an async context\n        import concurrent.futures\n\n        with concurrent.futures.ThreadPoolExecutor() as executor:\n            future = executor.submit(asyncio.run, list_ports())","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/imf/openbb_imf/utils/port_watch_helpers.py#L411-L447","documentation":"Catch-all wrapper in get_ports: any exception raised inside the async fetch (including the non-200 OpenBBError from 621, JSON decode errors, or client disconnects) is re-raised as an OpenBBError with the original exception and its args. It signals the ports lookup failed for an underlying reason detailed in the message.","triggerScenarios":"The session.get throws (DNS failure, TLS error, timeout), response.json() fails on a non-JSON error page, or the status-check OpenBBError at line 421 propagates into this handler.","commonSituations":"Offline environments, SSL certificate issues behind corporate proxies, ArcGIS returning an HTML error page instead of JSON, or any transient network fault during the ports-table bootstrap.","solutions":["Read the inner exception text after '->': it names the true cause (e.g. TimeoutError, ContentTypeError, status code).","Fix the underlying cause: network connectivity, proxy/TLS config, or simply retry for transient faults.","Verify the ports FeatureServer URL responds with JSON (curl with ?f=json).","If the inner error is the status-code OpenBBError, follow the guidance for that error (retry/backoff)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    ports = await get_ports()\nexcept OpenBBError as e:\n    msg = str(e)\n    if 'ClientConnectorError' in msg or 'Timeout' in msg:\n        handle_network_issue(msg)\n    elif 'Failed to fetch ports data' in msg:\n        handle_http_status(msg)\n    else:\n        raise","preventionTips":["Always read the embedded inner exception after '->' before retrying; the wrapper hides the class.","Use a local cache of the ports table so a single upstream hiccup does not break every PortWatch call.","Verify proxy/TLS config once in CI against services9.arcgis.com."],"tags":["network","imf","portwatch","wrapper","diagnostics"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}