n8n-io/n8n · warning · BadRequestError

This invite has been accepted already

Error message

This invite has been accepted already

What it means

A BadRequestError (HTTP 400) from processInvitationAcceptance when the resolved invitee already has a password set. A non-null invitee.password means the shell user was already filled out, so the invite is single-use and cannot be accepted again. Logged at debug with the inviteeId before throwing.

Source

Thrown at packages/cli/src/controllers/invitation.controller.ts:127

		if (users.length !== 2) {
			this.logger.debug(
				'Request to fill out a user shell failed because the inviter ID and/or invitee ID were not found in database',
				{
					inviterId,
					inviteeId,
				},
			);
			throw new BadRequestError('Invalid payload or URL');
		}

		const invitee = users.find((user) => user.id === inviteeId) as User;

		if (invitee.password) {
			this.logger.debug(
				'Request to fill out a user shell failed because the invite had already been accepted',
				{ inviteeId },
			);
			throw new BadRequestError('This invite has been accepted already');
		}

		invitee.firstName = firstName;
		invitee.lastName = lastName;
		invitee.password = await this.passwordUtility.hash(password);

		const updatedUser = await this.userRepository.save(invitee, { transaction: false });

		this.authService.issueCookie(res, updatedUser, false, req.browserId);

		this.eventService.emit('user-signed-up', {
			user: updatedUser,
			userType: 'email',
			wasDisabledLdapUser: false,
		});

		const publicInvitee = await this.userService.toPublic(invitee);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Tell the user the invite was already accepted and have them log in with the credentials they set.
  2. If they forgot the password, use the password-reset flow instead of the invite link.
  3. Guard the UI to disable the submit button after the first successful acceptance to prevent double-submit.
Defensive patterns

Strategy: try-catch

Validate before calling

// Client cannot know accept-state; rely on try/catch and redirect to login.

Try / catch

try {
  await api.post('/accept-invitation', { token, firstName, lastName, password });
} catch (e) {
  if (e.response?.status === 400 && /already been accepted/i.test(e.response.data.message)) {
    redirect('/signin');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST to the acceptance endpoint with a token whose invitee already completed setup (password is set). Re-clicking an already-used invite link, or a duplicate submission of the same form, triggers it.

Common situations: User clicks the invite link a second time after already setting up; browser retry/double-submit; shared invite link reused by a different person; the invitee forgot they completed setup and tries again.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/5695c6e4657649c7. Report an issue: GitHub.