{"record":{"id":"a9f5010f90e55c15","repo":"OpenBB-finance/OpenBB","slug":"unauthorized-fmp-request-code-msg","errorCode":null,"errorMessage":"Unauthorized FMP request -> {code} -> {msg}","messagePattern":"Unauthorized FMP request -> (.+?) -> (.+?)","errorType":"http","errorClass":"UnauthorizedError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py","lineNumber":17,"sourceCode":"\"\"\"FMP Helpers Module.\"\"\"\n\nfrom datetime import date\nfrom functools import lru_cache\nfrom typing import Any\n\nfrom openbb_core.app.model.abstract.error import OpenBBError\nfrom openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError\nfrom openbb_core.provider.utils.helpers import get_querystring\n\n\nasync def response_callback(response, _):\n    \"\"\"Use callback for make_request.\"\"\"\n    if response.status != 200:\n        msg = await response.text()\n        code = response.status\n        raise UnauthorizedError(f\"Unauthorized FMP request -> {code} -> {msg}\")\n\n    data = await response.json()\n\n    if isinstance(data, dict):\n        error_message = data.get(\"Error Message\", data.get(\"error\"))\n\n        if error_message is not None:\n            conditions = (\n                \"upgrade\" in error_message.lower()\n                or \"exclusive endpoint\" in error_message.lower()\n                or \"special endpoint\" in error_message.lower()\n                or \"premium query parameter\" in error_message.lower()\n                or \"subscription\" in error_message.lower()\n                or \"unauthorized\" in error_message.lower()\n                or \"premium\" in error_message.lower()\n            )\n\n            if conditions:","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py#L1-L35","documentation":"Raised in FMP's aiohttp response_callback whenever the HTTP status is not 200. It wraps any non-OK status (401/403 invalid key, 404 wrong endpoint, 429 rate limit, 5xx outage) as an UnauthorizedError with the status code and response body embedded, even though the actual cause may not be authorization.","triggerScenarios":"Any FMP request through openbb_fmp.utils.helpers.get_data where FMP returns non-200: expired or malformed api_key, exceeding the free-tier rate limit, requesting a deprecated endpoint version, or FMP server errors.","commonSituations":"Wrong/placeholder FMP_API_KEY environment variable, free-tier keys hitting the per-minute/per-day request cap, stale endpoint URLs after FMP version changes, or transient 502/503s from FMP infrastructure.","solutions":["Read the embedded status code in the message: 401/403 means fix the api key, 429 means rate limit - slow down or upgrade, 404 means the endpoint moved, 5xx means retry later","Verify the key with a trivial curl to https://financialmodelingprep.com/api/v3/profile/AAPL?apikey=KEY","Ensure the credential is set in OpenBB (openbb.accountCredentials or FMP_API_KEY env var) and not truncated/quoted incorrectly","For 429s, add request throttling in your own code or cache responses"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import requests\nr = requests.get(f\"https://financialmodelingprep.com/api/v3/profile/AAPL?apikey={api_key}\")\nassert r.status_code == 200, f'FMP key invalid or throttled: {r.status_code}'","typeGuard":null,"tryCatchPattern":"from openbb_core.provider.utils.errors import UnauthorizedError\ntry:\n    data = await fetcher.fetch_data(query, credentials)\nexcept UnauthorizedError as e:\n    msg = str(e)\n    if '429' in msg:\n        await asyncio.sleep(60)  # rate limited - back off and retry once\n    else:\n        raise  # genuine auth/key problem","preventionTips":["Verify the FMP key with a trivial request at application startup","Throttle FMP calls to stay under the plan's rate limit and cache responses","Parse the embedded status code from the message to branch handling"],"tags":["fmp","http","auth","rate-limit"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}