{"record":{"id":"c127f64292ddbaff","repo":"datawhalechina/hello-agents","slug":"str-e-c127f6","errorCode":null,"errorMessage":"str(e)","messagePattern":"str\\(e\\)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"Co-creation-projects/Apricity-InnocoreAI/api/routes/users.py","lineNumber":52,"sourceCode":"    \"\"\"创建用户\"\"\"\n    try:\n        user_id = await db_manager.create_user(\n            email=request.email,\n            profile=request.profile\n        )\n        \n        user = await db_manager.get_user(user_id)\n        \n        return UserResponse(\n            id=user[\"id\"],\n            email=user[\"email\"],\n            profile=user[\"profile\"],\n            created_at=user[\"created_at\"].isoformat() if user[\"created_at\"] else \"\"\n        )\n        \n    except Exception as e:\n        logger.error(f\"创建用户失败: {str(e)}\")\n        raise HTTPException(status_code=500, detail=str(e))\n\n@router.get(\"/{user_id}\", response_model=UserResponse)\nasync def get_user(user_id: str):\n    \"\"\"获取用户信息\"\"\"\n    try:\n        user = await db_manager.get_user(user_id)\n        if not user:\n            raise HTTPException(status_code=404, detail=\"用户不存在\")\n        \n        return UserResponse(\n            id=user[\"id\"],\n            email=user[\"email\"],\n            profile=user[\"profile\"],\n            created_at=user[\"created_at\"].isoformat() if user[\"created_at\"] else \"\"\n        )\n        \n    except HTTPException:\n        raise","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Apricity-InnocoreAI/api/routes/users.py#L34-L70","documentation":"Catch-all HTTPException 500 in the create-user endpoint (api/routes/users.py:52). Despite the '创建用户失败' log label, the except wraps user creation plus UserResponse construction; failures include DB write errors from db_manager and KeyError('id'/'email'/'profile') when get_user returns None because the just-created user could not be read back.","triggerScenarios":"POST create user where the database insert fails (duplicate email with a unique constraint, connection down); insert succeeds but immediate get_user read fails; returned row missing expected keys.","commonSituations":"Database not running or DSN misconfigured; duplicate registration with the same email; schema mismatch between db_manager's row mapping and UserResponse fields; created_at stored as string so .isoformat() raises AttributeError.","solutions":["Check the '创建用户失败' log for the underlying exception (IntegrityError, ConnectionError, KeyError, AttributeError).","If duplicate email, catch the integrity error and return 409 instead of 500.","Verify db_manager.get_user returns the full row the response model needs after insert.","Normalize timestamps before .isoformat() since DB drivers may return strings."],"exampleFix":"// before\nuser = await db_manager.get_user(user_id)\nreturn UserResponse(..., created_at=user[\"created_at\"].isoformat() if user[\"created_at\"] else \"\")\n// after\nuser = await db_manager.get_user(user_id)\nif not user:\n    raise HTTPException(status_code=500, detail=\"用户创建后读取失败\")\ncreated = user[\"created_at\"]\ncreated = created.isoformat() if hasattr(created, \"isoformat\") else (created or \"\")\nreturn UserResponse(id=user[\"id\"], email=user[\"email\"], profile=user[\"profile\"], created_at=created)","handlingStrategy":"validation","validationCode":"import json\njson.dumps(profile)  # profile must be JSON-serializable before create","typeGuard":"def is_serializable_profile(p) -> bool:\n    try:\n        json.dumps(p)\n        return True\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    resp = await client.post(\"/users/\", json=payload)\nexcept httpx.HTTPError:\n    raise\nif resp.status_code == 500 and 'duplicate' in resp.json().get('detail','').lower():\n    raise DuplicateUserError()","preventionTips":["Pre-check email uniqueness client-side where possible","Expect 500-with-detail to carry driver messages; parse only for logging","Reuse the creation response's user fields instead of re-GETting"],"tags":["fastapi","http-500","database","duplicate-key"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}