Significant-Gravitas/AutoGPT · warning · HTTPException

Invitation already revoked

Error message

Invitation already revoked

What it means

Raised by POST /api/invitations/{token}/decline when revokedAt is already set — an admin revoked the invitation. Decline is redundant for revoked invitations; note decline itself also works by setting revokedAt. HTTP 400.

Source

Thrown at autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py:234

    "/{token}/decline",
    summary="Decline invitation",
    tags=["invitations"],
    dependencies=[Security(requires_user)],
    status_code=204,
)
async def decline_invitation(
    token: str,
    user_id: Annotated[str, Security(get_user_id)],
) -> None:
    invitation = await prisma.orginvitation.find_unique(where={"token": token})
    if invitation is None:
        raise NotFoundError("Invitation not found")

    # State checks — same as accept_invitation
    if invitation.acceptedAt is not None:
        raise HTTPException(400, detail="Invitation already accepted")
    if invitation.revokedAt is not None:
        raise HTTPException(400, detail="Invitation already revoked")
    if invitation.expiresAt < datetime.now(timezone.utc):
        raise HTTPException(400, detail="Invitation has expired")

    # Verify the declining user's email matches the invitation
    declining_user = await prisma.user.find_unique(where={"id": user_id})
    if declining_user is None:
        raise HTTPException(401, detail="User not found")
    if declining_user.email.lower() != invitation.email.lower():
        raise HTTPException(
            403, detail="This invitation was sent to a different email address"
        )

    await prisma.orginvitation.update(
        where={"id": invitation.id},
        data={"revokedAt": datetime.now(timezone.utc)},
    )

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Treat this 400 as success — the intended end state (revoked) already holds; clear the invitation from the UI.
  2. Do not retry; re-fetch pending invitations to reconcile client state.
  3. Admins seeing this: the invitation is already inactive; no further action needed.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await api.post(`/api/invitations/${token}/decline`);
} catch (e) {
  if (e.status === 400 && /revoked/.test(e.detail)) { clearInvitation(token); return; }
  throw e;
}

Prevention

When it happens

Trigger: Admin revokes while the invitee still has the link open; invitee clicks decline on an already-revoked (or already-declined-from-another-device) invitation.

Common situations: Race between admin cleanup and user action; user clicks the decline link twice; two devices acting on the same invitation.

Related errors


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/11a462053b958ec5. Report an issue: GitHub.