datawhalechina/hello-agents · error · HTTPException
str(e)
Error message
str(e)
What it means
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.
Source
Thrown at Co-creation-projects/angelen-SoftwareDevHelper/src/main.py:195
"name": getattr(func, "name", ""),
"arguments": args,
"result": "" # 稍后填充
})
# 查找 tool 角色的消息(工具执行结果)
elif msg.role == "tool":
tool_call_id = getattr(msg, "tool_call_id", None)
if tool_call_id:
for tc_info in tool_calls_info:
if tc_info["id"] == tool_call_id:
tc_info["result"] = msg.content
break
# 保存助手消息(同时保存工具调用信息)
save_session_history(session_id, title, response, False, tool_calls=tool_calls_info)
return {"response": response, "session_id": session_id, "tool_calls": tool_calls_info}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/api/upload_project")
async def upload_project(session_id: str = Form(...), file: UploadFile = File(...)):
if not file.filename.endswith('.zip'):
raise HTTPException(status_code=400, detail="只接受 .zip 格式的压缩包")
upload_dir = os.path.join(os.path.dirname(__file__), "../outputs/uploads")
os.makedirs(upload_dir, exist_ok=True)
file_id = str(uuid.uuid4())
file_path = os.path.join(upload_dir, f"{file_id}_{file.filename}")
try:
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
agent = get_or_create_agent(session_id)
View on GitHub (pinned to 606a07d341)
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.
Example fix
// before
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# after
except Exception:
logging.exception("chat endpoint failed")
raise HTTPException(status_code=500, detail="Internal server error") Defensive patterns
Strategy: try-catch
Try / catch
# client side
import requests
try:
r = requests.post("/api/chat", json=payload, timeout=120)
if r.status_code >= 500:
logging.error("server error detail: %s", r.json().get("detail"))
# detail is str(e) of an unknown inner exception — do not parse it programmatically
r.raise_for_status()
except requests.Timeout:
retry_with_backoff() Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/f18cf03b93789cb2.
Report an issue: GitHub.