toeverything/AFFiNE · error · InvalidInvitation
invalid_invitation
invalid_invitation
Error message
Invalid invitation provided.
What it means
Thrown by the acceptInvitation GraphQL mutation when the inviteId resolves to an existing email invitation (a workspaceUser record), but the currently signed-in user's id does not match the invited user (role.userId). AFFiNE binds email invitations to one user, so a different account cannot consume them.
Solutions
- Sign out and sign back in as the exact user the invitation email was addressed to, then retry acceptInvitation.
- If the invitee should be different, ask the workspace owner to send a new invitation to the correct email address.
- Verify you are passing the inviteId of an email invitation and not a link invitation id (link invites take a different code path).
Defensive patterns
Strategy: validation
Validate before calling
// Before accepting, fetch invite info and compare the invitee with the session user
const invite = await gql.request(GET_INVITE_INFO, { inviteId });
if (!invite.isLink && invite.inviteeUserId && invite.inviteeUserId !== currentUser.id) {
// wrong account signed in — prompt switch instead of calling acceptInvitation
showSignInAs(invite.inviteeUserId);
} else {
await gql.request(ACCEPT_INVITATION, { inviteId });
} Try / catch
try {
await acceptInvitation(inviteId);
} catch (e) {
if (getErrorCode(e) === 'invalid_invitation' && isEmailInvite) {
// signed in as the wrong account — surface account-switch UI
}
} Prevention
- Fetch invite info first and compare inviteeUserId with the current session user before calling acceptInvitation.
- In the frontend invite flow, show which account is signed in before the accept step.
When it happens
Trigger: Calling acceptInvitation(inviteId) while authenticated as a user other than the one whose email received the invitation, e.g. the invitee clicks the accept link in the mail but the browser session belongs to another account (or a service/test account).
Common situations: Multiple accounts in one browser (personal + work), clicking an old invitation after switching accounts, or forwarding an invitation email to a teammate who tries to accept it from their own session.
Related errors
- authentication_required
- owner_can_not_leave_workspace
- space_access_denied
- access_denied
- action_forbidden
AI-assisted analysis of toeverything/AFFiNE@2af30773ae (2026-08-18).
Data as JSON: /api/errors/24879a9b525b2e62.
Report an issue: GitHub.
Appendix: source
Thrown at packages/backend/server/src/core/workspaces/resolvers/member.ts:580
return true;
}
@Mutation(() => Boolean)
async acceptInviteById(
@CurrentUser() user: CurrentUser,
@Args('inviteId') inviteId: string,
@Args('workspaceId', { deprecationReason: 'never used', nullable: true })
_workspaceId: string,
@Args('sendAcceptMail', {
nullable: true,
deprecationReason: 'never used',
})
_sendAcceptMail: boolean
) {
const role = await this.models.workspaceUser.getById(inviteId);
// invitation by email
if (role) {
if (user.id !== role.userId) {
throw new InvitationAccountMismatch();
}
await this.acceptInvitationByEmail(role);
} else {
// invitation by link
const invitation = await this.cache.get<{
workspaceId: string;
inviterUserId: string;
}>(`workspace:inviteLinkId:${inviteId}`);
if (!invitation) {
throw new InvalidInvitation();
}
const role = await this.models.workspaceUser.get(
invitation.workspaceId,View on GitHub (pinned to 2af30773ae)