{"record":{"id":"c6ca733eb126dd29","repo":"ZhuLinsen/daily_stock_analysis","slug":"error-c6ca73","errorCode":null,"errorMessage":"大盘复盘未返回可持久化报告","messagePattern":"大盘复盘未返回可持久化报告","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"api/v1/endpoints/analysis.py","lineNumber":167,"sourceCode":"            \"analyzer\": analyzer,\n            \"search_service\": search_service,\n            \"config\": runtime_config,\n            \"send_notification\": send_notification,\n            \"override_region\": effective_region,\n            \"return_structured\": True,\n            \"trigger_source\": \"api\",\n        }\n        if query_id:\n            review_kwargs[\"query_id\"] = query_id\n        logger.info(\n            \"[MarketReview] component=market_review action=background_start \"\n            \"trigger_source=api task_id=%s region=%s\",\n            query_id or \"-\",\n            effective_region,\n        )\n        report = run_market_review(**review_kwargs)\n        if not report:\n            raise RuntimeError(\"大盘复盘未返回可持久化报告\")\n        if hasattr(report, \"report\"):\n            return {\n                \"result\": report.report,\n                \"market_review_payload\": getattr(report, \"market_review_payload\", None),\n                \"region\": effective_region,\n            }\n        return {\"result\": report, \"region\": effective_region}\n    finally:\n        _release_market_review_lock(lock_token)\n\n\ndef _coalesce_text(*values: Any) -> Optional[str]:\n    for value in values:\n        if value is None:\n            continue\n        text = str(value).strip()\n        if text:\n            return text","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/api/v1/endpoints/analysis.py#L149-L185","documentation":"The market-review API background task raises RuntimeError('大盘复盘未返回可持久化报告') when run_market_review(...) (src/core/market_review.py:174) returns a falsy report — the pipeline swallowed its internal errors and produced no persistable text (analysis.py:160-167). run_market_review itself wraps the whole multi-region review in a broad try/except and returns None on failure, so this RuntimeError is the API layer refusing to persist an empty result.","triggerScenarios":"POST /analysis market-review style endpoint where every configured region's MarketAnalyzer.run_daily_review_with_snapshot() fails or returns empty (bad LLM/search credentials, upstream data provider outage); analyzer/search_service constructed with invalid config so report generation is skipped; notify-only or merge paths that suppress the report body under failure. Because a background lock (_release_market_review_lock in finally) serializes runs, the error surfaces as the task's failure result for the query_id/task_id.","commonSituations":"Expired or missing LLM API keys in the server env; data-provider fallback chain exhausted during a market holiday or data outage; region set to a market whose data source is unreachable from the deployment network; first run after upgrade where report template/language settings return empty strings.","solutions":["Inspect the server logs for the upstream [MarketReview] component errors — the RuntimeError here only tells you the report was empty, not why","Verify LLM and search provider credentials (the same config used for stock analysis) and re-run a single-region market review to isolate the failing region","Check data_provider health for the effective region (cn/us/hk) and retry after fixing connectivity","If regions are partially failing, consider narrowing market_review_region to the healthy region so a partial report still persists"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = trigger_market_review_api(payload)\nexcept TaskFailed as e:  # RuntimeError surfaced as task failure\n    if '未返回可持久化报告' in str(e):\n        # inspect server [MarketReview] logs; check LLM/search creds; narrow region; retry once\n        check_provider_credentials(); retry_with_single_region()\n    else:\n        raise","preventionTips":["Health-check LLM and search providers before scheduling market reviews","Start with a single region (cn) and add us/hk once each proves it can persist a report","Alert on empty-report outcomes so silent upstream failures are visible","Keep market_review_region explicit in deployment config to avoid accidental multi-region blast radius"],"tags":["market-review","analysis","runtime-error","llm","data-provider"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}