Significant-Gravitas/AutoGPT · error · NotFoundError
Invitation {invitation_id} not found
Error message
Invitation {invitation_id} not found What it means
Raised by DELETE revoke-invitation when the OrgInvitation record with the given invitation_id either does not exist or exists but its orgId does not match the org_id in the path. This prevents an admin of org A from revoking (or even probing) invitations of org B. It is a NotFoundError (mapped to HTTP 404).
Source
Thrown at autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py:128
@org_router.delete(
"/{invitation_id}",
summary="Revoke invitation",
tags=["orgs", "invitations"],
status_code=204,
)
async def revoke_invitation(
org_id: str,
invitation_id: str,
ctx: Annotated[
RequestContext,
Security(requires_org_permission(OrgAction.MANAGE_MEMBERS)),
],
) -> None:
_verify_org_path(ctx, org_id)
invitation = await prisma.orginvitation.find_unique(where={"id": invitation_id})
if invitation is None or invitation.orgId != org_id:
raise NotFoundError(f"Invitation {invitation_id} not found")
await prisma.orginvitation.update(
where={"id": invitation_id},
data={"revokedAt": datetime.now(timezone.utc)},
)
# --- Token-based endpoints (under /api/invitations) ---
@router.post(
"/{token}/accept",
summary="Accept invitation",
tags=["invitations"],
dependencies=[Security(requires_user)],
)
async def accept_invitation(
token: str,View on GitHub (pinned to 9c8bb5550f)
Solutions
- Confirm invitation_id comes from the pending-invitations list of the same org_id in the URL.
- If the 404 is unexpected, query prisma.orginvitation.find_unique for the id and inspect its orgId.
- Refresh the invitations table after the error and treat a 404 as 'already gone' — remove the row from the UI.
- Check for trailing whitespace or URL-encoding issues in the id parameter.
Example fix
# before
invitation = await prisma.orginvitation.find_unique(where={'id': invitation_id})
# after — verify org ownership before acting
invitation = await prisma.orginvitation.find_unique(where={'id': invitation_id})
if invitation is None or invitation.orgId != org_id:
return None # treat as already revoked/removed in the UI Defensive patterns
Strategy: try-catch
Validate before calling
const pending = await api.get(`/api/orgs/${orgId}/invitations/pending`).then(r => r.data);
const exists = pending.some(i => i.id === invitationId); Try / catch
try {
await api.delete(`/api/orgs/${orgId}/invitations/${invitationId}/revoke`);
} catch (e) {
if (e.status === 404) { removeInvitationFromUI(invitationId); return; }
throw e;
} Prevention
- Revoke only ids obtained from the same org's invitation list
- Treat 404 as already-gone and reconcile UI state
- Refresh the list after concurrent admin actions
When it happens
Trigger: POST/DELETE to /api/orgs/{org_id}/invitations/{invitation_id}/revoke with an invitation id from another org, a deleted invitation, or a malformed/typo'd id. Also when the invitation list in the UI is stale and the row was already revoked/removed.
Common situations: Admin has multiple orgs open and copies an invitation id across contexts; concurrent admin already revoked and cleanup removed the record; frontend keeps a cached list of invitations after org switch.
Related errors
- Organization {org_id} not found
- Invitation not found
- Graph #{graph_id} not found.
- Graph #{graph_id} not found.
- Execution not found
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/317bbfcbfe975b12.
Report an issue: GitHub.