{"record":{"id":"7675ce1ad65e2283","repo":"Significant-Gravitas/AutoGPT","slug":"invitation-not-found","errorCode":null,"errorMessage":"Invitation not found","messagePattern":"Invitation not found","errorType":"http","errorClass":"NotFoundError","httpStatus":404,"severity":"error","filePath":"autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py","lineNumber":151,"sourceCode":"    )\n\n\n# --- Token-based endpoints (under /api/invitations) ---\n\n\n@router.post(\n    \"/{token}/accept\",\n    summary=\"Accept invitation\",\n    tags=[\"invitations\"],\n    dependencies=[Security(requires_user)],\n)\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)","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/Significant-Gravitas/AutoGPT/blob/9c8bb5550f446ba5d3046b78896578742495b3cf/autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py#L133-L169","documentation":"Raised by POST /api/invitations/{token}/accept when no OrgInvitation row has the given token. Tokens are single-use opaque identifiers issued at invitation creation; a missing one means the invitation was deleted, the token is malformed, or it never existed. HTTP 404 via NotFoundError.","triggerScenarios":"User clicks an invitation link whose token was mistyped, truncated by an email client, or whose invitation record was removed. Also tokens from a different environment (test email link opened against production).","commonSituations":"Email client wraps/breaks long URLs; invitation deleted by an admin before acceptance; user reuses an old link after the row was purged; reverse proxy stripping path segments.","solutions":["Verify the full token arrives intact in the URL (no truncation, no encoding damage) by logging its length at the client.","Look up the token directly: prisma.orginvitation.find_unique(where={'token': token}) to confirm the record exists.","If the invitation was deleted/revoked-and-purged, ask the org admin to send a fresh invitation.","Check you are hitting the same backend/environment that generated the email link."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await api.post(`/api/invitations/${token}/accept`);\n} catch (e) {\n  if (e.status === 404) show('This invitation link is invalid or was removed. Ask for a new one.');\n  else throw e;\n}","preventionTips":["Send full, unbroken invitation URLs in emails (avoid wrapping)","Verify tokens reach the server untruncated before assuming corruption","Ensure email links target the environment that issued them"],"tags":["invitations","token","not-found","http-404"],"backgroundTag":null,"analyzedSha":"9c8bb5550f446ba5d3046b78896578742495b3cf","analyzedAt":"2026-08-14T17:17:21.957Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}