n8n-io/n8n · warning · BadRequestError

Token is required

Error message

Token is required

What it means

A BadRequestError (HTTP 400) from acceptInvitationWithToken when payload.token is falsy. The acceptance flow needs a JWT token (carrying inviterId/inviteeId) to proceed; without it the request is rejected immediately after the SSO check. Logged at debug as 'token is missing'.

Source

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

		ipRateLimit: { limit: 100, windowMs: 1 * Time.minutes.toMilliseconds },
	})
	async acceptInvitationWithToken(
		req: AuthlessRequest,
		res: Response,
		@Body payload: AcceptInvitationRequestDto,
	) {
		if (isSsoCurrentAuthenticationMethod()) {
			this.logger.debug(
				'Invite links are not supported on this system, please use single sign on instead.',
			);
			throw new BadRequestError(
				'Invite links are not supported on this system, please use single sign on instead.',
			);
		}

		if (!payload.token) {
			this.logger.debug('Request to accept invitation failed because token is missing');
			throw new BadRequestError('Token is required');
		}

		const { firstName, lastName, password } = payload;

		// Extract inviterId and inviteeId from JWT token
		const { inviterId, inviteeId } = await this.userService.getInvitationIdsFromPayload(
			payload.token,
		);

		return await this.processInvitationAcceptance(
			inviterId,
			inviteeId,
			firstName,
			lastName,
			password,
			req,
			res,
		);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Ensure the invite URL contains the token query param and that the frontend forwards it verbatim in the POST body.
  2. Validate the token is a non-empty string on the client before submitting.
  3. Check that reverse proxies do not strip the token from the URL or body.
  4. Re-request the invite link if the token was lost.

Example fix

// before
await api.post('/accept-invitation', { firstName, lastName, password });

// after
if (!token) throw new Error('Invite token missing from URL');
await api.post('/accept-invitation', { token, firstName, lastName, password });
Defensive patterns

Strategy: validation

Validate before calling

// Require a non-empty token string before POSTing.
function readInviteTokenFromUrl(): string | null {
  const t = new URLSearchParams(location.search).get('token');
  return typeof t === 'string' && t.length > 0 ? t : null;
}
const token = readInviteTokenFromUrl();
if (!token) throw new Error('Invite token missing from URL');

Type guard

function isNonEmptyString(v: unknown): v is string {
  return typeof v === 'string' && v.length > 0;
}

Try / catch

try {
  await api.post('/accept-invitation', { token, ...rest });
} catch (e) {
  if (e.response?.status === 400 && /token is required/i.test(e.response.data.message)) {
    notify('Invite link is incomplete — request a new one.');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST to accept-invitation with a body whose token field is missing, empty, null, or undefined. Common with malformed clients, hand-crafted requests, or a frontend bug that strips the token from the URL before POSTing.

Common situations: Frontend reads the token from the query string but the link was truncated; the user manually navigated to the page without the token; a proxy/load balancer strips query params; client-side bug that fails to include token in the body.

Related errors


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