{"record":{"id":"1ec0ff318185220b","repo":"Significant-Gravitas/AutoGPT","slug":"user-not-found-1ec0ff","errorCode":null,"errorMessage":"User not found","messagePattern":"User not found","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py","lineNumber":162,"sourceCode":")\nasync def accept_invitation(\n    token: str,\n    user_id: Annotated[str, Security(get_user_id)],\n) -> dict:\n    invitation = await prisma.orginvitation.find_unique(where={\"token\": token})\n    if invitation is None:\n        raise NotFoundError(\"Invitation not found\")\n    if invitation.acceptedAt is not None:\n        raise HTTPException(400, detail=\"Invitation already accepted\")\n    if invitation.revokedAt is not None:\n        raise HTTPException(400, detail=\"Invitation has been revoked\")\n    if invitation.expiresAt < datetime.now(timezone.utc):\n        raise HTTPException(400, detail=\"Invitation has expired\")\n\n    # Verify the accepting user's email matches the invitation\n    accepting_user = await prisma.user.find_unique(where={\"id\": user_id})\n    if accepting_user is None:\n        raise HTTPException(401, detail=\"User not found\")\n    if accepting_user.email.lower() != invitation.email.lower():\n        raise HTTPException(\n            403,\n            detail=\"This invitation was sent to a different email address\",\n        )\n\n    # Add user to org (idempotent — handles race condition from concurrent accepts)\n    try:\n        await org_db.add_org_member(\n            org_id=invitation.orgId,\n            user_id=user_id,\n            is_admin=invitation.isAdmin,\n            is_billing_manager=invitation.isBillingManager,\n            invited_by=invitation.invitedByUserId,\n        )\n    except UniqueViolationError:\n        # User is already a member — treat as success (idempotent)\n        pass","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py#L144-L180","documentation":"Raised by POST /api/invitations/{token}/accept when the authenticated user_id (from Security(get_user_id)) has no row in the User table. The token is valid, but the caller's identity does not resolve to a known user — typically a Supabase auth user that was deleted after the JWT was issued, or an inconsistent auth DB. HTTP 401.","triggerScenarios":"Accepting with a JWT for a user record deleted/deactivated between token issuance and the accept call; partially provisioned auth users (Supabase auth row exists, application User row missing).","commonSituations":"User account deleted while an invitation email was in flight; test environments with reset databases but reused tokens; sign-up flow interrupted before the User row was created.","solutions":["Have the user log out and back in to obtain a fresh token; if the account was deleted, re-register first.","Verify the User row exists: prisma.user.find_unique(where={'id': user_id}).","If auth and application users are out of sync, re-run the user provisioning/sync flow (Supabase webhook) for that account.","Do not retry the accept with the same token until identity is fixed — the token itself is fine."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const user = await api.get('/api/user/me').catch(() => null);\nif (!user) { await reauthenticate(); }","typeGuard":null,"tryCatchPattern":"try {\n  await api.post(`/api/invitations/${token}/accept`);\n} catch (e) {\n  if (e.status === 401) { await logout(); await login(); await retryAccept(); return; }\n  throw e;\n}","preventionTips":["Re-authenticate on 401 instead of retrying the same token","Verify the application User row exists after sign-up completes","Invalidate invitation flows when accounts are deleted"],"tags":["invitations","auth","user","http-401"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}