datawhalechina/hello-agents · error · HTTPException
Research failed
Error message
Research failed
What it means
HTTPException(500) raised by POST /research as a defensive catch-all when the deep-research agent run fails with anything other than ValueError. The original exception is chained (`from exc`) but intentionally hidden from the client ('Research failed') to avoid leaking internals — the real stack trace lives in the server logs only.
Source
Thrown at code/chapter14/helloagents-deepresearch/backend/src/main.py:127
config.use_tool_calling,
config.strip_thinking_tokens,
_mask_secret(config.llm_api_key),
)
@app.get("/healthz")
def health_check() -> Dict[str, str]:
return {"status": "ok"}
@app.post("/research", response_model=ResearchResponse)
def run_research(payload: ResearchRequest) -> ResearchResponse:
try:
config = _build_config(payload)
agent = DeepResearchAgent(config=config)
result = agent.run(payload.topic)
except ValueError as exc: # Likely due to unsupported configuration
raise HTTPException(status_code=400, detail=str(exc)) from exc
except Exception as exc: # pragma: no cover - defensive guardrail
raise HTTPException(status_code=500, detail="Research failed") from exc
todo_payload = [
{
"id": item.id,
"title": item.title,
"intent": item.intent,
"query": item.query,
"status": item.status,
"summary": item.summary,
"sources_summary": item.sources_summary,
"note_id": item.note_id,
"note_path": item.note_path,
}
for item in result.todo_items
]
return ResearchResponse(
report_markdown=(result.report_markdown or result.running_summary or ""),View on GitHub (pinned to 606a07d341)
Solutions
- Check the server-side traceback (the exception is chained and logged) — the client message is intentionally opaque
- Verify LLM credentials and network reachability of the LLM/search providers from the backend host
- Retry once: many failures here are transient (rate limits, network blips) during long research runs
- Add per-phase logging or shorter topics to narrow which agent stage failed
Example fix
# before
r = requests.post(f'{BASE}/research', json={'topic': t})
r.raise_for_status() # only 'Research failed', no cause
# after
r = requests.post(f'{BASE}/research', json={'topic': t}, timeout=600)
for attempt in range(2):
if r.status_code == 500:
time.sleep(5)
r = requests.post(f'{BASE}/research', json={'topic': t}, timeout=600)
else:
break
# meanwhile: inspect backend logs for the chained exception Defensive patterns
Strategy: retry
Validate before calling
import requests
# precheck provider reachability before long research runs
assert requests.get(f'{BASE}/healthz', timeout=5).status_code == 200, 'backend down'
# ensure LLM/search provider keys are configured server-side before submitting Try / catch
r = None
for attempt in range(2):
r = requests.post(f'{BASE}/research', json={'topic': topic}, timeout=600)
if r.status_code == 500 and attempt == 0:
time.sleep(10) # transient rate-limit/network; retry once
continue
r.raise_for_status() Prevention
- Remember the client message is masked — always correlate with server logs via request id
- Retry once with backoff: many deep-research failures are transient provider issues
- Pre-validate provider keys and quotas before long runs
- Keep topics narrowly scoped; long multi-phase runs amplify transient failure chances
When it happens
Trigger: LLM API key invalid/expired or provider unreachable during agent.run(); web-search backend rate-limited or offline; a bug in an agent phase (parsing, note writing) raising a non-ValueError exception; long runs hitting timeouts.
Common situations: Missing LLM_API_KEY in the deployed backend; search-provider quota exhausted mid-run; transient network failures during multi-step research; disk/path errors writing notes.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/a44d83acbb75c44b.
Report an issue: GitHub.