{"record":{"id":"a161b3af8ffb5e79","repo":"datawhalechina/hello-agents","slug":"error-a161b3","errorCode":null,"errorMessage":"议题不能为空","messagePattern":"议题不能为空","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"Co-creation-projects/meiguanxiHXX-historyReviewAgent/historical_review/debate_orchestrator.py","lineNumber":110,"sourceCode":"    llm_model: str | None = None,\n    llm_max_tokens: int | None = 4096,\n    llm_timeout: int | None = None,\n) -> Iterator[dict[str, Any]]:\n    \"\"\"\n    逐步产出辩论过程事件，供 SSE / 日志展示。\n\n    事件类型\n    --------\n    - progress: step, total, message\n    - round1_start / round1_end: role, content（end）\n    - digest_start / digest_end: content（end）\n    - round2_start / round2_end: role, content（end）\n    - synthesis_start / synthesis_end: content（end）\n    - complete: markdown（全文）\n    \"\"\"\n    topic = (topic or \"\").strip()\n    if not topic:\n        raise ValueError(\"议题不能为空\")\n\n    if llm is None:\n        llm = create_llm(\n            api_key=llm_api_key,\n            base_url=llm_base_url,\n            model=llm_model,\n            max_tokens=llm_max_tokens,\n            timeout=llm_timeout,\n            temperature=0.4,\n        )\n\n    step = 0\n\n    yield _yield_progress(step, f\"议题已接收：{topic[:80]}{'…' if len(topic) > 80 else ''}\")\n    step += 1\n\n    evidence_block = \"\"\n    if use_evidence_bundle:","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/meiguanxiHXX-historyReviewAgent/historical_review/debate_orchestrator.py#L92-L128","documentation":"run_historical_debate (the generator in debate_orchestrator.py) strips its topic argument and raises ValueError('议题不能为空') when the result is empty. This is deliberate input validation at the top of the debate pipeline: an empty topic would send meaningless prompts through four LLM phases (round1, digest, round2, synthesis), so the orchestrator refuses before creating an LLM client or emitting any events.","triggerScenarios":"Calling run_historical_debate(\"\"), run_historical_debate(None), or a topic of only whitespace/newlines; a UI passing an unvalidated textarea value straight through; a CLI arg like --topic '' ; upstream code trimming the topic to empty before forwarding it.","commonSituations":"Frontend form submitted with an empty topic field; programmatic callers forwarding user input without validation; trimming logic that reduces a punctuation-only topic to an empty string; API clients testing the endpoint with empty payloads.","solutions":["Pass a non-empty topic: run_historical_debate(\"评价唐朝灭亡的原因\") after stripping whitespace yourself.","If calling from the web layer, validate/strip req.topic in the endpoint (app.py already does this and returns HTTP 400) rather than letting the orchestrator raise.","In CLIs, argparse with required=True plus a check that topic.strip() is non-empty prevents silent empty strings.","Catch ValueError at the caller boundary and surface it as a user-facing '请输入议题' message instead of a stack trace."],"exampleFix":"# before\nrun_historical_debate(topic=user_input)\n# after\ntopic = (user_input or \"\").strip()\nif not topic:\n    raise SystemExit(\"请输入有效的议题\")\nrun_historical_debate(topic=topic)","handlingStrategy":"validation","validationCode":"topic = (topic or \"\").strip()\nif not topic:\n    raise ValueError(\"议题不能为空 — provide a non-empty debate topic\")\nmd = run_historical_debate(topic, ...)","typeGuard":"def is_valid_topic(topic: object) -> bool:\n    return isinstance(topic, str) and bool(topic.strip())","tryCatchPattern":"try:\n    md = collect_debate(run_historical_debate(topic, ...))\nexcept ValueError as e:\n    if \"议题不能为空\" in str(e):\n        # user-input problem — re-prompt, never retry the same input\n        raise UserInputError(str(e)) from e\n    raise","preventionTips":["Strip and validate topic at every entry point (CLI, web, API)","Validate in Pydantic models so HTTP callers get clean 400s","Never retry an input-validation error with the same payload"],"tags":["input-validation","python","argument-validation","orchestrator"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}