{"record":{"id":"af5cc1ace20459cb","repo":"ZhuLinsen/daily_stock_analysis","slug":"unsupported-daily-source-source","errorCode":null,"errorMessage":"Unsupported daily source: {source}","messagePattern":"Unsupported daily source: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/services/screening/daily.py","lineNumber":199,"sourceCode":"    direct HTTP K-line source before wrapper-based fallbacks. ``yfinance`` is\n    explicit-only (never part of ``auto``) and expects a US ticker rather than\n    an A-share code.\n    \"\"\"\n    normalized_code = _normalize_daily_code(code)\n    normalized_lookback_days = int(lookback_days)\n    src = _normalize_daily_source(source)\n    if src == \"auto\":\n        sources: tuple[str, ...] = (\n            (\"tushare\", \"tencent\", \"sina\", \"akshare\", \"baostock\")\n            if _has_tushare_token()\n            else (\"tencent\", \"sina\", \"akshare\", \"baostock\")\n        )\n        sources, source_order_notes = _rank_daily_sources_by_health(sources)\n    elif src in (\"akshare\", \"baostock\", \"tushare\", \"tencent\", \"sina\", \"yfinance\"):\n        sources = (src,)\n        source_order_notes = []\n    else:\n        raise ValueError(f\"Unsupported daily source: {source}\")\n\n    cache_path = None\n    if cache_dir is not None:\n        cache_path = _daily_history_cache_path(\n            cache_dir,\n            code=normalized_code,\n            source=src,\n            lookback_days=normalized_lookback_days,\n        )\n        cached = _read_daily_history_cache(cache_path, ttl_seconds=cache_ttl_seconds)\n        if cached is not None:\n            return cached\n\n    attempts = max(int(retries), 0) + 1\n    errors: list[str] = []\n    for current in sources:\n        disabled_reason = _source_disabled_reason(current)\n        if disabled_reason:","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/services/screening/daily.py#L181-L217","documentation":"ValueError raised by fetch_daily_history in the screening daily-data module when the source argument is not 'auto' and not one of the six explicit sources ('akshare', 'baostock', 'tushare', 'tencent', 'sina', 'yfinance'). _normalize_daily_source canonicalizes the input first; anything that still does not match the recognized names aborts before cache or network access.","triggerScenarios":"Calling fetch_daily_history(code, source='eastmoney'), source='em', source='yahoo' (the accepted name is 'yfinance'), or source='' / None coerced to an invalid default. 'auto' is special-cased to pick a ranked fallback chain (Tushare first when a token is configured).","commonSituations":"Users writing the provider's brand name ('eastmoney', 'yahoo') instead of the adapter name; passing a source string from an older config after an adapter rename; env/config typos like 'tushare ' handled by normalization but 'tusharre' not; hardcoding a source that requires optional deps that were renamed.","solutions":["Use one of: tencent, sina, akshare, baostock, tushare, yfinance, or 'auto' for the health-ranked fallback chain.","Fix aliases in config: 'yahoo' -> 'yfinance', 'em'/'eastmoney' -> use 'tencent' or 'auto'.","Validate config at startup: assert source in {'auto','akshare','baostock','tushare','tencent','sina','yfinance'}.","If you want resilience rather than a fixed provider, switch to source='auto' so a failing provider degrades instead of erroring."],"exampleFix":"# before\nfetch_daily_history('600519', source='yahoo')\n\n# after\nfetch_daily_history('600519', source='yfinance')\n# or let the module rank providers by health\nfetch_daily_history('600519', source='auto')","handlingStrategy":"validation","validationCode":"VALID_SOURCES = {'auto', 'tencent', 'sina', 'akshare', 'baostock', 'tushare', 'yfinance'}\nsource = (source or '').strip().lower()\nalias = {'yahoo': 'yfinance', 'em': 'auto', 'eastmoney': 'auto'}\nsource = alias.get(source, source)\nif source not in VALID_SOURCES:\n    raise ValueError(f'daily source must be one of {sorted(VALID_SOURCES)}')\ndf = fetch_daily_history(code, source=source)","typeGuard":"def is_valid_daily_source(value: str) -> bool:\n    return (value or '').strip().lower() in {'auto', 'tencent', 'sina', 'akshare', 'baostock', 'tushare', 'yfinance'}","tryCatchPattern":null,"preventionTips":["Use adapter names, not brand names ('yfinance', not 'yahoo').","Prefer source='auto' so provider outages degrade through the ranked fallback chain instead of failing.","Validate the source value when loading config so typos surface at startup."],"tags":["screening","daily-data","data-source","validation","enum"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}