datawhalechina/hello-agents · error · HTTPException
user_id 与 run 不匹配
Error message
user_id 与 run 不匹配
What it means
HTTP 403 raised by POST /diet/runs/{run_id}/replay when an optional user_id is supplied in the body and, after stripping, does not equal the run's stored user_id. It prevents replaying another user's run under your identity; omitting user_id in the body skips the check entirely.
Source
Thrown at Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/api/routes/diet.py:164
raise HTTPException(status_code=404, detail="未找到该饮食推荐 run")
return build_diet_observability(row)
@router.post("/diet/runs/{run_id}/replay")
async def diet_run_replay(
run_id: str,
body: DietReplayRequest | None = Body(default=None),
):
"""
阶段 3:用该 run 落库的 input 重跑流水线(新 run_id;列 replayed_from_run_id 与 output.replayed_from 溯源)。
Mock 工具确定性较高,LLM 输出仍可能不同。
"""
rid = run_id.strip()
row = get_diet_run(rid)
if not row:
raise HTTPException(status_code=404, detail="run 不存在")
if body and body.user_id and body.user_id.strip() != row["user_id"]:
raise HTTPException(status_code=403, detail="user_id 与 run 不匹配")
try:
return await replay_diet_run(rid)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
View on GitHub (pinned to 606a07d341)
Solutions
- Send the same user_id that owns the run, or omit user_id from the replay body.
- Retrieve the owning user via GET /diet/runs/{run_id} if unsure.
- Normalize (trim) user_id client-side to avoid false mismatches.
Example fix
# before
requests.post(f'{base}/diet/runs/{rid}/replay', json={'user_id': 'bob'}) # 403
# after
requests.post(f'{base}/diet/runs/{rid}/replay', json={'user_id': 'alice'})
# or simply:
requests.post(f'{base}/diet/runs/{rid}/replay') Defensive patterns
Strategy: validation
Validate before calling
row = requests.get(f"{base}/diet/runs/{rid}").json()
body = {"user_id": row["user_id"]} if include_owner else None
requests.post(f"{base}/diet/runs/{rid}/replay", json=body) Try / catch
try:
requests.post(f"{base}/diet/runs/{rid}/replay", json=body)
except HTTPError as e:
if e.response.status_code == 403:
body.pop("user_id", None) # omit optional owner check and retry once
requests.post(f"{base}/diet/runs/{rid}/replay")
else:
raise Prevention
- Either omit user_id in replay bodies or source it from the run row itself.
- Never auto-inject the session user into optional ownership fields.
- Normalize whitespace before comparing ids client-side.
When it happens
Trigger: POST /diet/runs/{rid}/replay with body {"user_id": "bob"} for a run created by 'alice' — including whitespace/case mismatches.
Common situations: Client auto-injecting the current logged-in user into every request body; switching test users between recommend and replay.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/30eeec1b5247f957.
Report an issue: GitHub.