datawhalechina/hello-agents · error · HTTPException

run 不存在

Error message

run 不存在

What it means

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.

Source

Thrown at Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/api/routes/diet.py:162

    row = get_diet_run(run_id.strip())
    if not row:
        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

  1. Fetch a valid run id from GET /diet/users/{user_id}/runs or a fresh /diet/recommend response.
  2. If replaying programmatically, check existence with GET /diet/runs/{run_id} first.
  3. Note the distinct 400 case: a run that exists but lacks a dict input fails in replay_diet_run, not here.

Example fix

# before
requests.post(f'{base}/diet/runs/old-id/replay')  # 404

# after
runs = requests.get(f'{base}/diet/users/{uid}/runs').json()['items']
rid = runs[0]['diet_run_id']
requests.post(f'{base}/diet/runs/{rid}/replay')
Defensive patterns

Strategy: validation

Validate before calling

row = requests.get(f"{base}/diet/runs/{rid}").json()
if not isinstance(row.get("input"), dict):
    raise ValueError("run has no persisted input; replay impossible")

Try / catch

try:
    new_run = requests.post(f"{base}/diet/runs/{rid}/replay").json()
except HTTPError as e:
    if e.response.status_code == 404:
        raise LookupError("original run missing; cannot replay")
    if e.response.status_code == 400:
        raise ValueError(e.response.json()["detail"])  # e.g. missing input
    raise

Prevention

When it happens

Trigger: POST /diet/runs/<unknown-id>/replay with optional body; run id non-existent after strip, or storage reset lost the run.

Common situations: Replaying from stale UI state after backend restart; automated tests replaying hard-coded ids.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/b232e1a15f8de397. Report an issue: GitHub.