{"record":{"id":"f4340e1672f627e2","repo":"OpenBB-finance/OpenBB","slug":"unauthorized-intrinio-request-message-f4340e","errorCode":null,"errorMessage":"Unauthorized Intrinio request -> {message}","messagePattern":"Unauthorized Intrinio request -> (.+?)","errorType":"exception","errorClass":"UnauthorizedError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/intrinio/openbb_intrinio/models/forward_sales_estimates.py","lineNumber":189,"sourceCode":"            if not data or not isinstance(data, dict) or not data.get(\"estimates\"):\n                warn(f\"Symbol Error: No data found for {symbol}\")\n            if isinstance(data, dict) and data.get(\"estimates\"):\n                new_data = data.get(\"estimates\")  # type: ignore\n                if new_data:\n                    results.extend(new_data)\n\n        if symbols:\n            await asyncio.gather(*[get_one(symbol) for symbol in symbols])\n            return results\n\n        async def fetch_callback(response, session):\n            \"\"\"Use callback for pagination.\"\"\"\n            data = await response.json()\n            error = data.get(\"error\", None)\n            if error:\n                message = data.get(\"message\", \"\")\n                if \"api key\" in message.lower():\n                    raise UnauthorizedError(\n                        f\"Unauthorized Intrinio request -> {message}\"\n                    )\n                raise OpenBBError(f\"Error: {error} -> {message}\")\n            if data.get(\"estimates\") and len(data.get(\"estimates\")) > 0:  # type: ignore\n                results.extend(data.get(\"estimates\"))  # type: ignore\n                while data.get(\"next_page\"):  # type: ignore\n                    next_page = data[\"next_page\"]  # type: ignore\n                    next_url = f\"{url}&next_page={next_page}\"\n                    data = await amake_request(next_url, session=session, **kwargs)\n                    if \"estimates\" in data and len(data.get(\"estimates\")) > 0:  # type: ignore\n                        results.extend(data.get(\"estimates\"))  # type: ignore\n            return results\n\n        url = f\"{BASE_URL}&{query_str}&api_key={api_key}\"\n\n        results = await amake_request(url, response_callback=fetch_callback, **kwargs)  # type: ignore\n\n        if not results:","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/intrinio/openbb_intrinio/models/forward_sales_estimates.py#L171-L207","documentation":"UnauthorizedError from the forward sales estimates fetch callback when the Intrinio body error's message contains 'api key'. Identical pattern to the EPS variant: the zacks/forward_sales endpoint rejected the credential, and the provider surfaces it as UnauthorizedError so the router maps it to an auth failure.","triggerScenarios":"equity/estimates/forward_sales with provider='intrinio' with missing/invalid/expired intrinio_api_key, or a key without the Zacks sales estimates entitlement; Intrinio returns body JSON with error plus a message mentioning the API key.","commonSituations":"Credentials never configured in the OpenBB hub; expired key; free tier; key corrupted by whitespace in env var or config file.","solutions":["Configure a valid key via obb.user.credentials.intrinio_api_key or INTRINIO_API_KEY.","Validate the key directly: curl 'https://api-v2.intrinio.com/zacks/forward_sales?api_key=KEY'.","Confirm plan entitlement for Zacks estimates data.","Re-enter the key cleanly, avoiding trailing newline."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"key = os.environ.get('INTRINIO_API_KEY')\nif not key or len(key.strip()) < 10:\n    raise RuntimeError('INTRINIO_API_KEY missing or obviously malformed')","typeGuard":null,"tryCatchPattern":"from openbb_core.provider.exceptions import UnauthorizedError\ntry:\n    res = obb.equity.estimates.forward_sales(symbol=sym, provider='intrinio')\nexcept UnauthorizedError:\n    refresh_intrinio_credentials()","preventionTips":["Centralize credential checks at startup","Strip whitespace when loading keys from env/config","Confirm Zacks entitlement covers sales estimates","Alert on 401 patterns in monitoring"],"tags":["intrinio","auth","api-key","estimates"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}