{"record":{"id":"caec051c79512ddb","repo":"datawhalechina/hello-agents","slug":"error-caec05","errorCode":null,"errorMessage":"需求必须是字符串","messagePattern":"需求必须是字符串","errorType":"exception","errorClass":"WorkflowExecutionError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/zenith191-RequirementClarifierAgent/src/workflow.py","lineNumber":118,"sourceCode":"            architecture=architecture,\n            risk_review=risk_review,\n            report=report,\n            quality=quality,\n        )\n\n    @staticmethod\n    def save_report(result: WorkflowResult, output_path: str | Path) -> Path:\n        \"\"\"以 UTF-8 保存最终 Markdown 报告。\"\"\"\n\n        path = Path(output_path)\n        path.parent.mkdir(parents=True, exist_ok=True)\n        path.write_text(result.report.rstrip() + \"\\n\", encoding=\"utf-8\")\n        return path\n\n    @staticmethod\n    def _validate_requirement(requirement: str) -> str:\n        if not isinstance(requirement, str):\n            raise WorkflowExecutionError(\"需求必须是字符串\")\n        requirement = requirement.strip()\n        if not requirement:\n            raise WorkflowExecutionError(\"需求不能为空\")\n        if len(requirement) > MAX_REQUIREMENT_LENGTH:\n            raise WorkflowExecutionError(\n                f\"需求文本不能超过 {MAX_REQUIREMENT_LENGTH} 个字符\"\n            )\n        return requirement\n\n    @staticmethod\n    def _run_agent(stage: str, agent: AgentLike, prompt: str) -> str:\n        try:\n            response = agent.run(prompt)\n        except Exception as exc:\n            raise WorkflowExecutionError(f\"{stage}阶段执行失败：{exc}\") from exc\n        if not isinstance(response, str) or not response.strip():\n            raise WorkflowExecutionError(f\"{stage}阶段返回了空结果\")\n        return response.strip()","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/zenith191-RequirementClarifierAgent/src/workflow.py#L100-L136","documentation":"Raised by RequirementClarifierWorkflow._validate_requirement (src/workflow.py:118) when the requirement argument is not a str instance. Since Python type hints are not enforced at runtime, passing bytes, a dict, or None into run() hits this explicit guard instead of failing later with a confusing prompt error.","triggerScenarios":"Calling workflow.run(requirement) with a dict parsed from JSON (e.g. {'text': '...'}), bytes read from a file, None from a failed upstream extraction, or an int/float ID.","commonSituations":"Gluing the workflow behind an API that decodes JSON and passes the whole request object; reading a file in 'rb' mode and forgetting .decode(); a None default from an optional form field flowing through.","solutions":["Convert to str before calling run(): decode bytes, extract the text field from the dict, or str()-serialize deliberately.","Fix the caller to pass requirement['text'] (or equivalent) rather than the wrapper object.","Add an assertion/log at the API boundary so non-string payloads are caught there with better context."],"exampleFix":"# before\nresult = workflow.run(req.json())  # dict!\n\n# after\nresult = workflow.run(req.json()[\"requirement\"])","handlingStrategy":"type-guard","validationCode":"def is_plain_text(v) -> bool:\n    return isinstance(v, str) and v.strip() != \"\"\n\n# at the API boundary\npayload = req.json()\nrequirement = payload.get(\"requirement\") if isinstance(payload, dict) else None\nif not is_plain_text(requirement):\n    raise ValueError(\"'requirement' must be a non-empty string\")","typeGuard":"def is_requirement_text(value: object) -> bool:\n    \"\"\"Narrows to a usable requirement string.\"\"\"\n    return isinstance(value, str) and bool(value.strip())\n\nassert is_requirement_text(requirement), type(requirement)","tryCatchPattern":"from src.workflow import WorkflowExecutionError\n\ntry:\n    result = workflow.run(requirement)\nexcept WorkflowExecutionError as e:\n    if \"必须是字符串\" in str(e):\n        requirement = str(requirement)  # deliberate coercion, then retry once\n        result = workflow.run(requirement)\n    else:\n        raise","preventionTips":["Validate and normalize input at the API/CLI boundary, not deep in the workflow.","Decode bytes and unwrap JSON objects before passing text downstream.","Type-hint the boundary (pydantic model with requirement: str) so FastAPI rejects wrong types for you."],"tags":["python","validation","type-error","workflow"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}