n8n-io/n8n · error · BadRequestError
Invalid invite URL
Error message
Invalid invite URL
What it means
BadRequestError (HTTP 400) 'Invalid invite URL' thrown at auth.controller.ts:247 after `userRepository.findManyByIds([inviterId, inviteeId])` returns fewer than two rows. The token decoded to two IDs but at least one no longer exists in the `user` table — typical of an invite whose target/inviter row was hard-deleted between issuance and resolve.
Source
Thrown at packages/cli/src/controllers/auth.controller.ts:247
if (!isWithinUsersLimit) {
this.logger.debug('Request to resolve signup token failed because of users quota reached', {
inviterId,
inviteeId,
});
throw new ForbiddenError(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED);
}
const users = await this.userRepository.findManyByIds([inviterId, inviteeId], {
includeRole: true,
});
if (users.length !== 2) {
this.logger.debug(
'Request to resolve signup token failed because the ID of the inviter and/or the ID of the invitee were not found in database',
{ inviterId, inviteeId },
);
throw new BadRequestError('Invalid invite URL');
}
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,
},View on GitHub (pinned to 5ac6606e81)
Solutions
- Ask an admin to re-issue a fresh invitation — the referenced user IDs no longer exist and the link cannot be repaired.
- Verify in the DB that both `inviterId` and `inviteeId` still exist in the `user` table; if the invitee was deleted, recreate the invite from Settings > Users.
- Audit deletion jobs that remove pending (passwordless) users to prevent recurrence.
- Check the token is the original, unmodified URL from the invitation email — manual edits to query params produce this.
Defensive patterns
Strategy: try-catch
Validate before calling
// Before resolving, verify both user IDs exist
import type { User } from '@n8n/db';
async function idsExist(repo: { findManyByIds(ids: string[]): Promise<User[]> }, ids: string[]) {
const found = await repo.findManyByIds(ids);
return found.length === ids.length;
}
// only call resolve-signup-token when idsExist(repo, [inviterId, inviteeId]) Try / catch
try {
await resolveSignupToken(token);
} catch (e) {
if (e instanceof BadRequestError && e.message === 'Invalid invite URL') {
// re-issue the invitation; do not loop on the same token
}
} Prevention
- Treat invite links as immutable; never hand-edit the token payload.
- Cascade-delete invites when their inviter or invitee user is removed.
- Audit pending invites after user-purge jobs.
When it happens
Trigger: Resolving a signup token where the invitee or inviter was deleted from the DB (e.g. admin purged the pending user, or the inviter left and was removed). Also reproducible by manually mutating the token payload to reference non-existent user IDs.
Common situations: Old invite links lingering after a tenant cleanup; GDPR/data-deletion jobs that prune pending invitees; stale email after the inviter's account was offboarded; forged or truncated tokens.
Related errors
- Invalid request
- The invitation was likely either deleted or already claimed
- Maximum number of users reached
- Maximum number of users reached
- Cannot delete your own user
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/1aa3f9f79379dc26.
Report an issue: GitHub.