{"record":{"id":"b232e1a15f8de397","repo":"datawhalechina/hello-agents","slug":"run-b232e1","errorCode":null,"errorMessage":"run 不存在","messagePattern":"run 不存在","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/api/routes/diet.py","lineNumber":162,"sourceCode":"    row = get_diet_run(run_id.strip())\n    if not row:\n        raise HTTPException(status_code=404, detail=\"未找到该饮食推荐 run\")\n    return build_diet_observability(row)\n\n\n@router.post(\"/diet/runs/{run_id}/replay\")\nasync def diet_run_replay(\n    run_id: str,\n    body: DietReplayRequest | None = Body(default=None),\n):\n    \"\"\"\n    阶段 3：用该 run 落库的 input 重跑流水线（新 run_id；列 replayed_from_run_id 与 output.replayed_from 溯源）。\n    Mock 工具确定性较高，LLM 输出仍可能不同。\n    \"\"\"\n    rid = run_id.strip()\n    row = get_diet_run(rid)\n    if not row:\n        raise HTTPException(status_code=404, detail=\"run 不存在\")\n    if body and body.user_id and body.user_id.strip() != row[\"user_id\"]:\n        raise HTTPException(status_code=403, detail=\"user_id 与 run 不匹配\")\n    try:\n        return await replay_diet_run(rid)\n    except ValueError as e:\n        raise HTTPException(status_code=400, detail=str(e))\n","sourceCodeStart":144,"sourceCodeEnd":169,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/api/routes/diet.py#L144-L169","documentation":"HTTP 404 raised by POST /diet/runs/{run_id}/replay when the target run does not exist. Replay re-executes the pipeline using the input persisted with the original run, so a missing row (or one without a dict 'input' column — that variant raises ValueError -> 400 in the service layer) cannot be replayed.","triggerScenarios":"POST /diet/runs/<unknown-id>/replay with optional body; run id non-existent after strip, or storage reset lost the run.","commonSituations":"Replaying from stale UI state after backend restart; automated tests replaying hard-coded ids.","solutions":["Fetch a valid run id from GET /diet/users/{user_id}/runs or a fresh /diet/recommend response.","If replaying programmatically, check existence with GET /diet/runs/{run_id} first.","Note the distinct 400 case: a run that exists but lacks a dict input fails in replay_diet_run, not here."],"exampleFix":"# before\nrequests.post(f'{base}/diet/runs/old-id/replay')  # 404\n\n# after\nruns = requests.get(f'{base}/diet/users/{uid}/runs').json()['items']\nrid = runs[0]['diet_run_id']\nrequests.post(f'{base}/diet/runs/{rid}/replay')","handlingStrategy":"validation","validationCode":"row = requests.get(f\"{base}/diet/runs/{rid}\").json()\nif not isinstance(row.get(\"input\"), dict):\n    raise ValueError(\"run has no persisted input; replay impossible\")","typeGuard":null,"tryCatchPattern":"try:\n    new_run = requests.post(f\"{base}/diet/runs/{rid}/replay\").json()\nexcept HTTPError as e:\n    if e.response.status_code == 404:\n        raise LookupError(\"original run missing; cannot replay\")\n    if e.response.status_code == 400:\n        raise ValueError(e.response.json()[\"detail\"])  # e.g. missing input\n    raise","preventionTips":["Only replay runs produced by the current pipeline version (input persisted).","Keep the original run id stable in client state until replay completes.","Handle both 404 (missing run) and 400 (missing input) distinctly."],"tags":["fastapi","http-404","replay","diet-api"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}