{"record":{"id":"459bc5ce2badbcb5","repo":"TauricResearch/TradingAgents","slug":"alpha-vantage-api-key-invalid-or-missing-notice","errorCode":null,"errorMessage":"Alpha Vantage API key invalid or missing: {notice}","messagePattern":"Alpha Vantage API key invalid or missing: (.+?)","errorType":"exception","errorClass":"AlphaVantageNotConfiguredError","httpStatus":null,"severity":"error","filePath":"tradingagents/dataflows/alpha_vantage_common.py","lineNumber":110,"sourceCode":"    # JSON). A non-JSON body is normal data.\n    try:\n        response_json = json.loads(response_text)\n    except json.JSONDecodeError:\n        return response_text\n\n    # Alpha Vantage reports problems via \"Information\" / \"Note\". Classify so a\n    # genuine rate limit and an invalid/missing key aren't conflated (#991):\n    # rate-limit phrasing is checked first because those notices also mention\n    # \"API key\" (\"your API key ... 25 requests per day\").\n    notice = response_json.get(\"Information\") or response_json.get(\"Note\")\n    if notice:\n        low = notice.lower()\n        if any(m in low for m in (\"rate limit\", \"requests per day\", \"call frequency\", \"premium\")):\n            raise AlphaVantageRateLimitError(f\"Alpha Vantage rate limit exceeded: {notice}\")\n        if \"api key\" in low or \"apikey\" in low:\n            # Reuse the existing \"not configured\" error so a bad key surfaces as\n            # a real, actionable failure rather than a mislabeled rate limit (#991).\n            raise AlphaVantageNotConfiguredError(f\"Alpha Vantage API key invalid or missing: {notice}\")\n\n    return response_text\n\n\n\ndef _filter_csv_by_date_range(csv_data: str, start_date: str, end_date: str) -> str:\n    \"\"\"\n    Filter CSV data to include only rows within the specified date range.\n\n    Args:\n        csv_data: CSV string from Alpha Vantage API\n        start_date: Start date in yyyy-mm-dd format\n        end_date: End date in yyyy-mm-dd format\n\n    Returns:\n        Filtered CSV string\n    \"\"\"\n    if not csv_data or csv_data.strip() == \"\":","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/TauricResearch/TradingAgents/blob/a33fd4c0f134485a43553a2c23a63cb14adbd88f/tradingagents/dataflows/alpha_vantage_common.py#L92-L128","documentation":"Raised by _make_api_request() in tradingagents/dataflows/alpha_vantage_common.py when Alpha Vantage's 'Information'/'Note' notice mentions 'api key'/'apikey' without rate-limit phrasing — i.e. the key is invalid, not passed, or lacks entitlement. It deliberately reuses AlphaVantageNotConfiguredError (a VendorNotConfiguredError and ValueError) so a bad key surfaces as an actionable configuration failure rather than being mislabeled a rate limit (#991). The router treats it as 'vendor unavailable' and tries the next vendor.","triggerScenarios":"Setting ALPHA_VANTAGE_API_KEY to a wrong/revoked/demo key; a key with spaces or quotes pasted from email; a valid key used for an endpoint its tier does not allow (non-rate-limit premium notice). Distinct from a genuinely missing env var (error [0]) — here the key is present but rejected.","commonSituations":"Copy-paste artifacts (trailing whitespace, curly quotes) in the env var; using the literature 'demo' key on real endpoints; expired keys after account changes; keys rotated but the old value still in .env or CI secrets.","solutions":["Verify the key: curl 'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=IBM&apikey=YOURKEY' should return data, not an 'Information' note","Fix the stored value: strip whitespace/quotes, re-export ALPHA_VANTAGE_API_KEY, restart the process (and update CI/Docker secrets)","If the notice is about entitlement, upgrade the key tier or switch that tool to a vendor that covers it (tool_vendors config)","Add 'yfinance' after alpha_vantage in data_vendors so the router falls through when the key is rejected"],"exampleFix":"# before\nexport ALPHA_VANTAGE_API_KEY=\" demo \"   # stray spaces/invalid key\n# -> AlphaVantageNotConfiguredError: Alpha Vantage API key invalid or missing: ...\n\n# after\nexport ALPHA_VANTAGE_API_KEY=\"YOUR_CLEAN_KEY\"   # validated via a direct curl first\n# optional resilience: {\"data_vendors\": {\"stock_data\": \"alpha_vantage,yfinance\"}}","handlingStrategy":"validation","validationCode":"import os, requests\n\ndef alpha_vantage_key_works() -> bool | str:\n    key = (os.getenv(\"ALPHA_VANTAGE_API_KEY\") or \"\").strip()\n    if not key:\n        return False\n    r = requests.get(\"https://www.alphavantage.co/query\", params={\"function\": \"TIME_SERIES_DAILY\", \"symbol\": \"IBM\", \"apikey\": key}, timeout=15)\n    js = r.json()\n    return not (\"Information\" in js or \"Note\" in js)","typeGuard":null,"tryCatchPattern":"from tradingagents.dataflows.alpha_vantage_common import AlphaVantageNotConfiguredError\n\ntry:\n    data = get_historical_prices(sym, start, end)\nexcept AlphaVantageNotConfiguredError as e:\n    if \"invalid or missing\" in str(e):\n        alert_ops(f\"Alpha Vantage key rejected: {e}\")  # config bug, do not retry\n    raise","preventionTips":["Strip whitespace/quotes when setting the env var; never copy keys with formatting","Smoke-test the key with one direct curl/query after setup and after rotation","Keep CI/Docker secrets in sync when the key is rotated","Include a second vendor in the chain so a rejected key degrades instead of failing the run"],"tags":["api-key","alpha-vantage","configuration","authentication"],"backgroundTag":null,"analyzedSha":"a33fd4c0f134485a43553a2c23a63cb14adbd88f","analyzedAt":"2026-08-14T19:45:16.920Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}