{"record":{"id":"489cfc35b1815981","repo":"HKUDS/Vibe-Trading","slug":"trading-212-api-returned-http-response-status-cod","errorCode":null,"errorMessage":"Trading 212 API returned HTTP {response.status_code}: {_error_message(response)}","messagePattern":"Trading 212 API returned HTTP (.+?): (.+?)","errorType":"http","errorClass":"Trading212APIError","httpStatus":null,"severity":"error","filePath":"agent/src/trading/connectors/trading212/sdk.py","lineNumber":432,"sourceCode":"        auth = (config.api_key, config.api_secret)\n    else:\n        headers[\"Authorization\"] = config.api_key\n    try:\n        response = requests.request(\n            method.upper(),\n            url,\n            headers=headers,\n            auth=auth,\n            params=dict(params or {}),\n            timeout=config.timeout,\n        )\n    except requests.RequestException as exc:\n        raise Trading212APIError(f\"Trading 212 request failed: {exc}\") from exc\n\n    if response.status_code in (401, 403):\n        raise Trading212APIError(\"Trading 212 API authentication failed: check api_key/api_secret.\")\n    if response.status_code >= 400:\n        raise Trading212APIError(f\"Trading 212 API returned HTTP {response.status_code}: {_error_message(response)}\")\n    if not response.content:\n        return None\n    try:\n        return response.json()\n    except ValueError as exc:\n        raise Trading212APIError(\"Trading 212 API returned invalid JSON.\") from exc\n\n\ndef _error_message(response: requests.Response) -> str:\n    try:\n        payload = response.json()\n    except ValueError:\n        return response.text.strip() or response.reason or \"request failed\"\n    if isinstance(payload, Mapping):\n        for key in (\"message\", \"error\", \"detail\", \"title\"):\n            value = payload.get(key)\n            if value:\n                return str(value)","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connectors/trading212/sdk.py#L414-L450","documentation":"Raised by _request for any HTTP response with status >= 400 that is not 401/403. The message includes the status code and _error_message(response), which extracts the API's own error payload when the body is JSON, so you can see the server-side reason.","triggerScenarios":"Any _get call hitting 400 (bad query params), 404 (wrong path/base_url), 429 (rate limited), or 5xx (server error) from the Trading 212 API.","commonSituations":"Rate limiting on polling loops calling get_positions frequently; base_url with a stale API path after a version change; malformed params passed by caller code; transient 5xx during API incidents.","solutions":["Read the status code and _error_message body in the message — fix params/path accordingly","For 429, slow down polling and add backoff between calls","For 5xx, retry with exponential backoff or check the Trading 212 status page","For 404, verify base_url and the endpoint path are current for your API version"],"exampleFix":"# before\nwhile True:\n    positions = get_positions(config)  # hammers API -> 429\n# after\nimport time\nwhile True:\n    try:\n        positions = get_positions(config)\n    except Trading212APIError as exc:\n        time.sleep(30)  # backoff, then retry\n        continue\n    time.sleep(60)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"import time\nfor attempt in range(3):\n    try:\n        data = get_positions(config)\n        break\n    except Trading212APIError as exc:\n        if \"HTTP 429\" in str(exc) or \"HTTP 5\" in str(exc):\n            time.sleep(2 ** attempt)\n            continue\n        raise","preventionTips":["Rate-limit polling loops client-side (sleep between calls)","Parse the status code out of the message to distinguish retryable (429/5xx) from permanent (400/404) failures","Monitor for status-code shifts after upgrading API versions"],"tags":["trading212","http","rate-limit","api"],"backgroundTag":"http-error-response","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}