{"record":{"id":"caf68fccdb9c191c","repo":"Significant-Gravitas/AutoGPT","slug":"job-belongs-to-a-different-user","errorCode":null,"errorMessage":"job belongs to a different user","messagePattern":"job belongs to a different user","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"warning","filePath":"autogpt_platform/backend/backend/api/features/admin/memory_admin_routes.py","lineNumber":805,"sourceCode":"    request: Request,\n    user_id: Annotated[str, Path(description=\"User id or 'me'\")],\n    job_id: Annotated[str, Path(description=\"Job id returned by the POST\")],\n    caller_id: Annotated[str, Depends(get_user_id)],\n    jwt_payload: Annotated[dict, Security(get_jwt_payload)],\n) -> DreamJobStatus:\n    \"\"\"Read the current status of a fire-and-forget dream pass job.\"\"\"\n    target = _resolve_user_id(user_id, caller_id)\n    _audit_cross_user_access(\n        request=request,\n        caller_id=caller_id,\n        target_id=target,\n        jwt_payload=jwt_payload,\n    )\n    status = await read_status(kind=\"dream_pass\", job_id=job_id)\n    if status is None:\n        raise HTTPException(status_code=404, detail=\"job not found\")\n    if status.user_id != target:\n        raise HTTPException(status_code=403, detail=\"job belongs to a different user\")\n    return DreamJobStatus.model_validate(status.model_dump())\n\n\n@router.post(\"/{user_id}/ratification\", response_model=RatificationResult)\nasync def trigger_ratification_pass(\n    request: Request,\n    user_id: Annotated[str, Path(description=\"User id or 'me'\")],\n    caller_id: Annotated[str, Depends(get_user_id)],\n    jwt_payload: Annotated[dict, Security(get_jwt_payload)],\n) -> RatificationResult:\n    \"\"\"Trigger an on-demand ratification sweep for the user (in isolation).\n\n    Forwards to ``Scheduler.execute_ratification_pass_now``. Runs ONLY\n    the ratification supersession sweep — does NOT run dream pass or\n    community rebuild. Useful for testing ratification behavior\n    without the full nightly fan-out.\n    \"\"\"\n    target = _resolve_user_id(user_id, caller_id)","sourceCodeStart":787,"sourceCodeEnd":823,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/admin/memory_admin_routes.py#L787-L823","documentation":"HTTP 403 from the dream-pass job status endpoint. The job was found, but its stored user_id does not equal the resolved target user (from the path's user_id or 'me'). This is an authorization guard preventing one user/admin from reading another user's job status through a mismatched path.","triggerScenarios":"GET /{user_a}/dream/{job_id}/status where job_id belongs to user_b. Happens when the path user_id is swapped after triggering (e.g. triggered as 'me' then polled with an explicit different id), when an admin fronts the call with the wrong tenant id, or when test code mixes fixtures from two users.","commonSituations":"Frontend stores job_id globally instead of per-user and a different logged-in user polls it; admin consoles that pass the admin's own id as user_id while replaying a customer's job_id; concurrent test sessions sharing job ids across user fixtures.","solutions":["Make the path user_id identical to the one used when triggering the job (use 'me' for the caller's own jobs)","Store job_id scoped per user in the client, not in a global variable","In admin tooling, pass the target user's id consistently in both the trigger and status calls","If cross-user inspection is required, use the admin path with the job owner's user_id, not the caller's"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"assert trigger_user_id == poll_user_id, \"path user must match the job owner\"","typeGuard":null,"tryCatchPattern":"except httpx.HTTPStatusError as e:\n    if e.response.status_code == 403:\n        # job exists but belongs to another user — do not retry with same pair\n        ...","preventionTips":["Use 'me' for self-service jobs so the path user is always correct","Store {user_id, kind, job_id} together, never job_id alone","Treat 403 as a wiring bug in your caller, not a transient error"],"tags":["http-403","authorization","job-status","dream-pass"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}