Significant-Gravitas/AutoGPT · warning · HTTPException
job belongs to a different user
Error message
job belongs to a different user
What it means
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.
Source
Thrown at autogpt_platform/backend/backend/api/features/admin/memory_admin_routes.py:805
request: Request,
user_id: Annotated[str, Path(description="User id or 'me'")],
job_id: Annotated[str, Path(description="Job id returned by the POST")],
caller_id: Annotated[str, Depends(get_user_id)],
jwt_payload: Annotated[dict, Security(get_jwt_payload)],
) -> DreamJobStatus:
"""Read the current status of a fire-and-forget dream pass job."""
target = _resolve_user_id(user_id, caller_id)
_audit_cross_user_access(
request=request,
caller_id=caller_id,
target_id=target,
jwt_payload=jwt_payload,
)
status = await read_status(kind="dream_pass", job_id=job_id)
if status is None:
raise HTTPException(status_code=404, detail="job not found")
if status.user_id != target:
raise HTTPException(status_code=403, detail="job belongs to a different user")
return DreamJobStatus.model_validate(status.model_dump())
@router.post("/{user_id}/ratification", response_model=RatificationResult)
async def trigger_ratification_pass(
request: Request,
user_id: Annotated[str, Path(description="User id or 'me'")],
caller_id: Annotated[str, Depends(get_user_id)],
jwt_payload: Annotated[dict, Security(get_jwt_payload)],
) -> RatificationResult:
"""Trigger an on-demand ratification sweep for the user (in isolation).
Forwards to ``Scheduler.execute_ratification_pass_now``. Runs ONLY
the ratification supersession sweep — does NOT run dream pass or
community rebuild. Useful for testing ratification behavior
without the full nightly fan-out.
"""
target = _resolve_user_id(user_id, caller_id)View on GitHub (pinned to 9c8bb5550f)
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
Defensive patterns
Strategy: validation
Validate before calling
assert trigger_user_id == poll_user_id, "path user must match the job owner"
Try / catch
except httpx.HTTPStatusError as e:
if e.response.status_code == 403:
# job exists but belongs to another user — do not retry with same pair
... Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- job not found
- This invitation was sent to a different email address
- Not a member of this organization
- ENTERPRISE subscription changes must be managed by an admini
- Failed to start OAuth flow
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/caf68fccdb9c191c.
Report an issue: GitHub.