{"record":{"id":"f18cf03b93789cb2","repo":"datawhalechina/hello-agents","slug":"str-e-f18cf0","errorCode":null,"errorMessage":"str(e)","messagePattern":"str\\(e\\)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"Co-creation-projects/angelen-SoftwareDevHelper/src/main.py","lineNumber":195,"sourceCode":"                            \"name\": getattr(func, \"name\", \"\"),\n                            \"arguments\": args,\n                            \"result\": \"\" # 稍后填充\n                        })\n            # 查找 tool 角色的消息（工具执行结果）\n            elif msg.role == \"tool\":\n                tool_call_id = getattr(msg, \"tool_call_id\", None)\n                if tool_call_id:\n                    for tc_info in tool_calls_info:\n                        if tc_info[\"id\"] == tool_call_id:\n                            tc_info[\"result\"] = msg.content\n                            break\n\n        # 保存助手消息（同时保存工具调用信息）\n        save_session_history(session_id, title, response, False, tool_calls=tool_calls_info)\n\n        return {\"response\": response, \"session_id\": session_id, \"tool_calls\": tool_calls_info}\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=str(e))\n\n@app.post(\"/api/upload_project\")\nasync def upload_project(session_id: str = Form(...), file: UploadFile = File(...)):\n    if not file.filename.endswith('.zip'):\n        raise HTTPException(status_code=400, detail=\"只接受 .zip 格式的压缩包\")\n\n    upload_dir = os.path.join(os.path.dirname(__file__), \"../outputs/uploads\")\n    os.makedirs(upload_dir, exist_ok=True)\n    \n    file_id = str(uuid.uuid4())\n    file_path = os.path.join(upload_dir, f\"{file_id}_{file.filename}\")\n    \n    try:\n        with open(file_path, \"wb\") as buffer:\n            shutil.copyfileobj(file.file, buffer)\n            \n        agent = get_or_create_agent(session_id)\n        ","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/angelen-SoftwareDevHelper/src/main.py#L177-L213","documentation":"A catch-all `except Exception as e` at the end of a FastAPI chat endpoint re-raises every failure as `HTTPException(status_code=500, detail=str(e))`. The 'message' is therefore not a fixed string but the repr/text of whatever underlying exception escaped the agent-run pipeline (LLM API error, KeyError on message roles, JSON serialization of tool_calls, etc.). It surfaces raw internal exception text to the HTTP client.","triggerScenarios":"POST to the chat endpoint when any exception escapes: the LLM provider rejects the API key or times out, `save_session_history` fails to serialize `tool_calls`/response objects, or the response object structure (msg.role/tool_call_id attributes) differs from what the loop expects.","commonSituations":"Missing/expired LLM API key in .env, rate limits from the model provider, unserializable objects passed to session persistence, or a provider SDK version change that alters message attributes.","solutions":["Reproduce with the same request and read the server console/traceback: `detail=str(e)` only echoes the inner exception, so the true cause is the original traceback, not the 500 body.","Verify LLM env vars (API key, base URL, model name) are set in the environment the server was started in.","Check that `response` and `tool_calls_info` contain only JSON-serializable values before `save_session_history`.","Replace the blanket handler with typed handling: log the exception with `logging.exception`, return a generic detail, and map known errors (auth, timeout, validation) to 4xx/502."],"exampleFix":"// before\nexcept Exception as e:\n    raise HTTPException(status_code=500, detail=str(e))\n\n# after\nexcept Exception:\n    logging.exception(\"chat endpoint failed\")\n    raise HTTPException(status_code=500, detail=\"Internal server error\")","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"# client side\nimport requests\ntry:\n    r = requests.post(\"/api/chat\", json=payload, timeout=120)\n    if r.status_code >= 500:\n        logging.error(\"server error detail: %s\", r.json().get(\"detail\"))\n        # detail is str(e) of an unknown inner exception — do not parse it programmatically\n    r.raise_for_status()\nexcept requests.Timeout:\n    retry_with_backoff()","preventionTips":["Smoke-test the LLM config (key/base URL/model) with a minimal request before wiring the chat endpoint.","Ensure response/tool_calls values passed to save_session_history are JSON-serializable (str() complex objects first).","Keep server logs enabled: detail=str(e) is useless without the server-side traceback."],"tags":["fastapi","http-500","catch-all","llm","python"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}