{"record":{"id":"65de26e219e8ad3e","repo":"datawhalechina/hello-agents","slug":"str-e-65de26","errorCode":null,"errorMessage":"工作流执行失败: {str(e)}","messagePattern":"工作流执行失败: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"Co-creation-projects/Apricity-InnocoreAI/api/routes/workflow.py","lineNumber":231,"sourceCode":"                })\n        \n        # 完成工作流\n        results[\"status\"] = \"completed\"\n        results[\"summary\"] = {\n            \"total_papers\": len(papers),\n            \"analyzed_papers\": len(analyses),\n            \"generated_citations\": len(citations),\n            \"keywords\": request.keywords\n        }\n        \n        logger.info(f\"[工作流 {workflow_id}] 完成\")\n        return results\n        \n    except HTTPException:\n        raise\n    except Exception as e:\n        logger.error(f\"工作流执行失败: {str(e)}\")\n        raise HTTPException(status_code=500, detail=f\"工作流执行失败: {str(e)}\")\n\n@router.post(\"/search-and-analyze\", response_model=Dict[str, Any])\nasync def search_and_analyze(request: WorkflowRequest):\n    \"\"\"\n    简化工作流：搜索 + 分析\n    只执行搜索和分析步骤\n    \"\"\"\n    try:\n        results = {\n            \"status\": \"running\",\n            \"steps\": []\n        }\n        \n        # 步骤 1: 搜索论文\n        from api.routes.papers import search_papers, PaperSearchRequest\n        \n        search_result = await search_papers(PaperSearchRequest(\n            keywords=request.keywords,","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Apricity-InnocoreAI/api/routes/workflow.py#L213-L249","documentation":"Catch-all HTTPException 500 '工作流执行失败: {str(e)}' at api/routes/workflow.py:231 wrapping the entire full-workflow run. Any step failure (search, analysis, writing, citation) after the per-step handling — or a failure in assembling the final results dict — bubbles to this handler, which correctly re-raises HTTPException first but wraps everything else.","triggerScenarios":"POST /workflow/full where a later step (writing/review/citation) throws unexpectedly; result aggregation raising (len() on None, missing keys); cancellation of the request mid-workflow.","commonSituations":"LLM API quota exhausted mid-run; partial pipeline state after an earlier soft-failed step; long runs hitting proxy timeouts that surface as client-side aborts then server-side errors.","solutions":["Read the '工作流执行失败' log with traceback to identify the failing step.","Run the failing step standalone (e.g. POST /workflow/search-and-analyze) to isolate it.","Check LLM/search API keys, quota, and network egress.","Give each step the same try/except+record pattern as step 1 so partial results return with status='failed' instead of an opaque 500."],"exampleFix":"// before\nexcept Exception as e:\n    logger.error(f\"工作流执行失败: {str(e)}\")\n    raise HTTPException(status_code=500, detail=f\"工作流执行失败: {str(e)}\")\n// after\nexcept Exception as e:\n    logger.exception(\"工作流执行失败\")\n    results[\"status\"] = \"failed\"\n    results[\"error\"] = \"工作流执行失败\"\n    return results","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    results = await client.post(\"/workflow/full\", json=payload, timeout=900).json()\nexcept httpx.TimeoutException:\n    # fall back to submit + poll pattern\n    raise\nif results.get(\"status\") == \"failed\" or client_last_status >= 500:\n    identify_failed_step(results); retry_with_wider_keywords()","preventionTips":["Use long client timeouts; workflows are slow","Retry only after confirming quota/keys are valid","Map failed steps from the partial results payload before retrying"],"tags":["fastapi","http-500","workflow-pipeline","error-leak"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}