datawhalechina/hello-agents · error · HTTPException
{str(exc)}
Error message
{str(exc)} What it means
HTTPException(400) raised by POST /research in the chapter14 deep-research backend when _build_config(payload) or the agent raises ValueError — the route deliberately maps ValueError to a client-error 400 with the original message. It marks configuration the request asked for as unsupported (bad model name, bad provider, invalid search settings) rather than a server fault.
Source
Thrown at code/chapter14/helloagents-deepresearch/backend/src/main.py:125
config.max_web_research_loops,
config.fetch_full_page,
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
]
View on GitHub (pinned to 606a07d341)
Solutions
- Read the detail field — it is the original ValueError text naming the unsupported value
- Fix the request payload (correct model/provider names, valid numeric fields) per the ResearchRequest schema
- If the value should be supported, extend _build_config's allowlist rather than catching the 400
Example fix
# before
payload = {"topic": "quantum computing", "model": "gpt-99"} # -> 400
# after
payload = {"topic": "quantum computing", "model": "deepseek-chat"} # a supported id
r = requests.post(f'{BASE}/research', json=payload)
if r.status_code == 400:
print('Bad request config:', r.json()['detail']) Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED_MODELS = {'deepseek-chat', 'deepseek-reasoner', ...} # mirror _build_config
def valid_research_payload(p: dict) -> bool:
return (
bool(str(p.get('topic', '')).strip())
and p.get('model', 'default') in SUPPORTED_MODELS
) Type guard
def is_supported_model(m) -> bool:
return isinstance(m, str) and m in SUPPORTED_MODELS Try / catch
r = requests.post(f'{BASE}/research', json=payload)
if r.status_code == 400:
raise ValueError(f'Unsupported research config: {r.json()["detail"]}') # actionable message
r.raise_for_status() Prevention
- Publish the supported model/provider list in the API docs and validate client-side
- Pass through the 400 detail to users — it names the exact unsupported value
- Add schema-level enums to ResearchRequest so bad values fail at validation, not inside _build_config
When it happens
Trigger: Payload specifying an unknown/unsupported model or provider; malformed enum-ish fields (e.g. invalid search depth or max iterations as strings) that _build_config parses and rejects; empty/whitespace topic triggering validation ValueError.
Common situations: Frontend sending a model id removed after a backend update; user-typed config fields passed straight through; API consumers guessing field values instead of following the schema.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/63b60bbed7f7a061.
Report an issue: GitHub.