datawhalechina/hello-agents · warning · HTTPException
议题不能为空
Error message
议题不能为空
What it means
The POST /api/debate handler in historical_review/web/app.py strips req.topic and raises HTTPException(400, '议题不能为空') when the result is empty. This is the web-layer twin of the orchestrator's ValueError (error 247): the endpoint validates the DebateRequest body before spending LLM tokens. A 400 here means the JSON body's topic field was missing, null, empty, or whitespace-only.
Source
Thrown at Co-creation-projects/meiguanxiHXX-historyReviewAgent/historical_review/web/app.py:80
@app.get("/")
async def index_page() -> FileResponse:
html = _STATIC / "index.html"
if not html.is_file():
raise HTTPException(status_code=500, detail="前端文件缺失,请检查 historical_review/web/static/")
return FileResponse(html)
@app.get("/api/health")
async def health() -> dict[str, str]:
return {"status": "ok"}
@app.post("/api/debate", response_model=DebateResponse)
async def run_debate(req: DebateRequest) -> DebateResponse:
topic = req.topic.strip()
if not topic:
raise HTTPException(status_code=400, detail="议题不能为空")
key_err = _api_key_error(req)
if key_err:
return DebateResponse(ok=False, error=key_err)
def _work() -> str:
return run_historical_debate(
topic,
use_evidence_bundle=req.use_evidence_bundle,
debate_temperature=req.debate_temperature,
synthesizer_temperature=req.synthesizer_temperature,
llm_api_key=req.api_key.strip() if req.api_key else None,
llm_base_url=req.base_url.strip() if req.base_url else None,
llm_model=req.model.strip() if req.model else None,
llm_max_tokens=req.max_tokens,
llm_timeout=req.timeout,
)
View on GitHub (pinned to 606a07d341)
Solutions
- Send a real topic in the request body: curl -X POST /api/debate -H 'Content-Type: application/json' -d '{"topic":"评价隋炀帝", "api_key":"sk-or-..."}'.
- Add client-side validation: disable submit until topic.trim().length > 0.
- Make the Pydantic model enforce it — topic: str = Field(min_length=1) with a validator rejecting whitespace-only strings — so the 400 message is consistent for all callers.
- Handle HTTP 400 in the client and show the detail message to the user.
Example fix
# before
class DebateRequest(BaseModel):
topic: str
# after
from pydantic import field_validator
class DebateRequest(BaseModel):
topic: str
@field_validator("topic")
@classmethod
def topic_not_blank(cls, v: str) -> str:
if not v.strip():
raise ValueError("议题不能为空")
return v.strip() Defensive patterns
Strategy: validation
Validate before calling
topic = (req.topic or "").strip()
if not topic:
return JSONResponse(status_code=400, content={"detail": "议题不能为空"}) Type guard
def is_valid_debate_request(req) -> bool:
return isinstance(getattr(req, "topic", None), str) and bool(req.topic.strip()) Try / catch
# client side
resp = requests.post(url, json=payload, timeout=60)
if resp.status_code == 400:
show_user(resp.json()["detail"]) # display '议题不能为空' instead of crashing
else:
resp.raise_for_status() Prevention
- Add Pydantic validators so blank topics are rejected with a 400 at the model layer
- Disable submit buttons until topic.trim() is non-empty
- Handle 400 responses explicitly in every API client
When it happens
Trigger: curl -X POST /api/debate with {"topic": ""} or omitting topic; frontend submitting the form before the user types anything; a client sending topic: null; whitespace/punctuation-only input that strips to empty.
Common situations: Missing required-field check in the frontend form; automated scripts probing the API with empty payloads; textarea default value being empty string and validation living only server-side.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/349e8005b33c449d.
Report an issue: GitHub.