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

  1. Check the server-side traceback (the exception is chained and logged) — the client message is intentionally opaque
  2. Verify LLM credentials and network reachability of the LLM/search providers from the backend host
  3. Retry once: many failures here are transient (rate limits, network blips) during long research runs
  4. 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

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.