n8n-io/n8n · error · BadRequestError

Invalid request

Error message

Invalid request

What it means

BadRequestError (HTTP 400) 'Invalid request' thrown at auth.controller.ts:267 when the inviter row exists but has no `email`. The inviter is expected to be a fully set-up user (with email); a missing email means the inviter account is incomplete/broken, so the resolve refuses to expose inviter first/last name.

Source

Thrown at packages/cli/src/controllers/auth.controller.ts:267

		const invitee = users.find((user) => user.id === inviteeId);
		if (!invitee || invitee.password) {
			this.logger.error('Invalid invite URL - invitee already setup', {
				inviterId,
				inviteeId,
			});
			throw new BadRequestError('The invitation was likely either deleted or already claimed');
		}

		const inviter = users.find((user) => user.id === inviterId);
		if (!inviter?.email) {
			this.logger.error(
				'Request to resolve signup token failed because inviter does not exist or is not set up',
				{
					inviterId: inviter?.id,
				},
			);
			throw new BadRequestError('Invalid request');
		}

		this.eventService.emit('user-invite-email-click', { inviter, invitee });

		const { firstName, lastName } = inviter;
		return { inviter: { firstName, lastName } };
	}

	/** Log out a user */
	@Post('/logout')
	async logout(req: AuthenticatedRequest, res: Response) {
		await this.authService.invalidateToken(req);
		this.authService.clearCookie(res);
		return { loggedOut: true };
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the inviter row in the DB: `SELECT id,email FROM user WHERE id=<inviterId>` — if email is empty, repair the inviter's profile first.
  2. Re-invite from a different, fully-set-up owner/admin account.
  3. Re-run or fix the SSO/LDAP sync that dropped the email.
  4. If the inviter no longer exists, re-create the invitation under a valid owner.
Defensive patterns

Strategy: validation

Validate before calling

// Before resolving, ensure the inviter has an email set
async function inviterIsValid(u: { email?: string | null } | null) {
  return !!u && !!u.email;
}
// gate resolve on inviterIsValid(await userRepo.findOneBy({ id: inviterId }))

Type guard

const inviterHasEmail = (u: unknown): u is { id: string; email: string } =>
  typeof u === 'object' && u !== null && typeof (u as any).email === 'string' && (u as any).email.length > 0;

Try / catch

try {
  await resolveSignupToken(token);
} catch (e) {
  if (e instanceof BadRequestError && e.message === 'Invalid request') {
    // escalate to admin: inviter row is corrupted (no email)
  }
}

Prevention

When it happens

Trigger: An invitation was created by an inviter whose account was later reset or corrupted such that `email` is null/empty. Rare in normal flows since owners always have email; surfaces with direct DB tampering or partial migrations.

Common situations: DB migration/import that nullified inviter emails; manual SQL edits to the user table; an SSO/LDAP sync that wiped an email field after an invite was sent.

Related errors


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