{"record":{"id":"744feb4efde45539","repo":"n8n-io/n8n","slug":"the-invitation-was-likely-either-deleted-or-alread","errorCode":null,"errorMessage":"The invitation was likely either deleted or already claimed","messagePattern":"The invitation was likely either deleted or already claimed","errorType":"exception","errorClass":"BadRequestError","httpStatus":400,"severity":"error","filePath":"packages/cli/src/controllers/auth.controller.ts","lineNumber":256,"sourceCode":"\t\tconst users = await this.userRepository.findManyByIds([inviterId, inviteeId], {\n\t\t\tincludeRole: true,\n\t\t});\n\n\t\tif (users.length !== 2) {\n\t\t\tthis.logger.debug(\n\t\t\t\t'Request to resolve signup token failed because the ID of the inviter and/or the ID of the invitee were not found in database',\n\t\t\t\t{ inviterId, inviteeId },\n\t\t\t);\n\t\t\tthrow new BadRequestError('Invalid invite URL');\n\t\t}\n\n\t\tconst invitee = users.find((user) => user.id === inviteeId);\n\t\tif (!invitee || invitee.password) {\n\t\t\tthis.logger.error('Invalid invite URL - invitee already setup', {\n\t\t\t\tinviterId,\n\t\t\t\tinviteeId,\n\t\t\t});\n\t\t\tthrow new BadRequestError('The invitation was likely either deleted or already claimed');\n\t\t}\n\n\t\tconst inviter = users.find((user) => user.id === inviterId);\n\t\tif (!inviter?.email) {\n\t\t\tthis.logger.error(\n\t\t\t\t'Request to resolve signup token failed because inviter does not exist or is not set up',\n\t\t\t\t{\n\t\t\t\t\tinviterId: inviter?.id,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthrow new BadRequestError('Invalid request');\n\t\t}\n\n\t\tthis.eventService.emit('user-invite-email-click', { inviter, invitee });\n\n\t\tconst { firstName, lastName } = inviter;\n\t\treturn { inviter: { firstName, lastName } };\n\t}","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/controllers/auth.controller.ts#L238-L274","documentation":"BadRequestError (HTTP 400) 'The invitation was likely either deleted or already claimed' thrown at auth.controller.ts:256 when the invitee row exists but either is falsy or already has a `password` set. Once an invitee completes signup and stores a password, the invite is considered claimed and the resolve endpoint refuses to re-enter the setup flow.","triggerScenarios":"User clicks an old invite link after already completing signup once (e.g. re-clicking after password set, or a duplicate link in mailbox). Also when the invitee row was soft-deleted/marked pending but a password already exists.","commonSituations":"Invitee reopens the welcome email days later; forwarded invites where two people clicked; password reset flows that mistakenly route back through the invite resolve URL; bookmarked invite links.","solutions":["If not yet registered: ask an admin to delete the partially-set-up invitee row and re-invite, producing a fresh token.","If already registered: use the normal 'Forgot password' flow instead of the invite link.","Admin: in Settings > Users confirm the invitee's status — a password column set to non-null means claimed.","Communicate to invitees that the link is single-use and to complete signup in one sitting."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before opening invite link, check the invitee row\nasync function isUnclaimed(user: { password: string | null } | null) {\n  return !!user && !user.password;\n}\n// gate the resolve call on isUnclaimed(await userRepo.findOneBy({ id: inviteeId }))","typeGuard":"const isUnclaimedInvitee = (u: unknown): u is { id: string; password: null } =>\n  typeof u === 'object' && u !== null && 'id' in u && 'password' in u && (u as any).password === null;","tryCatchPattern":"try {\n  await resolveSignupToken(token);\n} catch (e) {\n  if (e instanceof BadRequestError && /deleted or already claimed/.test(e.message)) {\n    // route the user to 'Forgot password' if they already have an account\n  }\n}","preventionTips":["Tell invitees the link is single-use and to finish signup in one sitting.","Auto-invalidate the invite token once a password is set.","Surface 'already claimed' to the user with a login link instead of an error page."],"tags":["auth","invitation","bad-request","signup"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}