{"record":{"id":"735983f908e6f35a","repo":"datawhalechina/hello-agents","slug":"user-id","errorCode":null,"errorMessage":"user_id 不能为空","messagePattern":"user_id 不能为空","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"warning","filePath":"Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/api/routes/diet.py","lineNumber":46,"sourceCode":"        default_factory=lambda: [\"convenience_store\", \"delivery\"],\n        description=\"可购买渠道标签\",\n    )\n    activity_context: str = Field(default=\"\", max_length=2000, description=\"运动/睡眠等上下文\")\n    free_notes: str = Field(\n        default=\"\", max_length=2000, description=\"额外说明（如只有便利店）\"\n    )\n\n\nclass DietRecommendRequest(BaseModel):\n    user_id: str = Field(..., min_length=1, max_length=256)\n    context: DietContext\n\n    @field_validator(\"user_id\")\n    @classmethod\n    def strip_uid(cls, v: str) -> str:\n        v = v.strip()\n        if not v:\n            raise ValueError(\"user_id 不能为空\")\n        return v\n\n\nclass DietReplayRequest(BaseModel):\n    \"\"\"可选：传入 user_id 时必须与 run 一致，防止误重放。\"\"\"\n\n    user_id: Optional[str] = Field(default=None, max_length=256)\n\n\nclass DietReflectRequest(BaseModel):\n    user_id: str = Field(..., min_length=1, max_length=256)\n    diet_run_id: str = Field(..., min_length=8, max_length=64)\n    followed: bool = Field(..., description=\"是否按上次推荐执行\")\n    reason_code: Optional[\n        Literal[\"cant_buy\", \"too_late\", \"dont_want\", \"executed_ok\", \"other\"]\n    ] = Field(default=None, description=\"未执行或总结原因类型\")\n    reason_detail: Optional[str] = Field(default=None, max_length=2000)\n","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/api/routes/diet.py#L28-L64","documentation":"Pydantic field_validator error on the DietRecommendRequest model. The user_id field must be 1-256 chars, and after stripping whitespace it must be non-empty. A value of only whitespace (e.g. \" \") passes min_length=1 but fails this validator, producing a 422 response from FastAPI.","triggerScenarios":"POST /diet/recommend with user_id set to a whitespace-only or empty string. The endpoint returns HTTP 422 with the validator message in the response body.","commonSituations":"Frontend sending an untrimmed form field; copy-paste user IDs containing only spaces; test fixtures using placeholder strings like ' '.","solutions":["Trim user_id on the client before sending and ensure it is a real identifier.","If you control the API and want whitespace-only to become a normal 400, validate before model construction.","Check the 422 response body: it names the field (user_id) and this message."],"exampleFix":"# before\nrequests.post(url, json={\"user_id\": \"   \", \"context\": ctx})  # 422\n\n# after\nuid = \"u123\".strip()\nassert uid\nrequests.post(url, json={\"user_id\": uid, \"context\": ctx})","handlingStrategy":"validation","validationCode":"uid = user_id.strip() if isinstance(user_id, str) else \"\"\nif not uid:\n    raise ValueError(\"user_id must be a non-empty trimmed string\")\nbody = {\"user_id\": uid, \"context\": ctx}","typeGuard":"def is_valid_user_id(v) -> bool:\n    return isinstance(v, str) and 1 <= len(v.strip()) <= 256","tryCatchPattern":null,"preventionTips":["Trim all user-provided identifiers at the client boundary.","Add shared request DTOs/types so both frontend and backend apply the same rule.","Treat FastAPI 422 bodies as validation feedback: they name the exact field."],"tags":["pydantic","fastapi","validation","http-422"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}