ZhuLinsen/daily_stock_analysis · error · DataFetchError

[Finnhub] API key not configured

Error message

[Finnhub] API key not configured

What it means

FinnhubFetcher refuses to fetch when no API key is resolvable: __init__ reads config.finnhub_api_key or env FINNHUB_API_KEY, and _fetch_raw_data hard-guards on the result. The constructor only logs at debug ('fetcher disabled'), so the first visible symptom is often this DataFetchError at fetch time.

Source

Thrown at data_provider/finnhub_fetcher.py:43


class FinnhubFetcher(BaseFetcher):
    name = "FinnhubFetcher"
    priority = 2

    def __init__(self):
        from src.config import get_config
        config = get_config()
        self._api_key = getattr(config, 'finnhub_api_key', None) or os.getenv('FINNHUB_API_KEY')
        if not self._api_key:
            logger.debug("[Finnhub] API key not configured, fetcher disabled")

    def _is_us_stock(self, stock_code: str) -> bool:
        return is_us_stock_code(stock_code)

    def _fetch_raw_data(self, stock_code: str, start_date: str, end_date: str) -> pd.DataFrame:
        if not self._api_key:
            raise DataFetchError("[Finnhub] API key not configured")
        if not self._is_us_stock(stock_code):
            raise DataFetchError(f"[Finnhub] {stock_code} is not a US stock")

        symbol = stock_code.strip().upper()
        start_ts = int(datetime.strptime(start_date, '%Y-%m-%d').timestamp())
        end_ts = int(datetime.strptime(end_date, '%Y-%m-%d').timestamp())

        url = f"{_FINNHUB_BASE_URL}/stock/candle"
        params = {
            'symbol': symbol,
            'resolution': 'D',
            'from': start_ts,
            'to': end_ts,
            'token': self._api_key,
        }

        try:
            self.random_sleep(0.3, 0.8)

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Set FINNHUB_API_KEY in .env (and .env.example documentation) or via environment for the process/container.
  2. Confirm the value reaches get_config() — print/log whether config.finnhub_api_key is populated at startup.
  3. If intentionally keyless, rely on manager routing (YFinance) instead of calling FinnhubFetcher directly; treat this error as 'source disabled'.

Example fix

# before: nothing set -> raise
# after: .env
FINNHUB_API_KEY=your_key_here
Defensive patterns

Strategy: validation

Validate before calling

import os
from src.config import get_config
cfg = get_config()
has_key = bool(getattr(cfg, 'finnhub_api_key', None) or os.getenv('FINNHUB_API_KEY'))
if not has_key:
    logger.info('Finnhub disabled — relying on YFinance/AlphaVantage for US')

Type guard

def finnhub_configured() -> bool:
    return bool(getattr(get_config(), 'finnhub_api_key', None) or os.getenv('FINNHUB_API_KEY'))

Try / catch

try:
    df = finnhub.get_daily_data(symbol, ...)
except DataFetchError as e:
    if 'API key not configured' in str(e):
        skip_source('finnhub')  # config issue — do not retry

Prevention

When it happens

Trigger: Calling FinnhubFetcher._fetch_raw_data/get_daily_data with neither config.finnhub_api_key nor the FINNHUB_API_KEY env var set — common in fresh clones, CI, or Docker images that don't pass the env var.

Common situations: .env missing FINNHUB_API_KEY; docker run without -e FINNHUB_API_KEY; GitHub Actions secret not wired; config loaded before .env is read so getattr returns None.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/e2428da909780c9d. Report an issue: GitHub.