RocketChat/Rocket.Chat · error · Meteor.Error

error-token-does-not-exists

error-token-does-not-exists

Error message

Token does not exist

What it means

removePersonalAccessTokenOfUser first resolves the token by name via Users.findPersonalAccessTokenByTokenNameAndUserId({ userId, tokenName }); if no token with that name exists for the user, it throws error-token-does-not-exists before modifying loginTokens.

Solutions

  1. Treat it as success if the goal is 'token must not exist' — it is already gone.
  2. Otherwise verify the exact token name against the user's token list and retry.
  3. Guard re-runnable scripts so a missing token is not an error.

Example fix

// before
await Meteor.callAsync('personalAccessTokens:removeToken', { tokenName });

// after — idempotent delete
try {
	await Meteor.callAsync('personalAccessTokens:removeToken', { tokenName });
} catch (e: any) {
	if (e?.error !== 'error-token-does-not-exists') throw e; // already removed: fine
}
Defensive patterns

Strategy: fallback

Validate before calling

const token = await Users.findPersonalAccessTokenByTokenNameAndUserId({ userId, tokenName });
if (!token) return; // goal already achieved: token absent

Try / catch

try {
	await Meteor.callAsync('personalAccessTokens:removeToken', { tokenName });
} catch (e: any) {
	if (e?.error !== 'error-token-does-not-exists') throw e; // already gone — treat as success
}

Prevention

When it happens

Trigger: Calling personalAccessTokens:removeToken for an already-removed token (double delete), a name that never existed, or a case-mismatched name.

Common situations: Idempotent-delete races in UIs (double-click), cleanup scripts re-running, tokens already rotated/removed elsewhere.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/4cd06381d9ef462f. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/imports/personal-access-tokens/server/api/methods/removeToken.ts:25

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		'personalAccessTokens:removeToken'(params: { tokenName: string }): Promise<void>;
	}
}

export const removePersonalAccessTokenOfUser = async (tokenName: string, userId: string): Promise<void> => {
	if (!(await hasPermissionAsync(userId, 'create-personal-access-tokens'))) {
		throw new Meteor.Error('not-authorized', 'Not Authorized', {
			method: 'personalAccessTokens:removeToken',
		});
	}
	const tokenExist = await Users.findPersonalAccessTokenByTokenNameAndUserId({
		userId,
		tokenName,
	});
	if (!tokenExist) {
		throw new Meteor.Error('error-token-does-not-exists', 'Token does not exist', {
			method: 'personalAccessTokens:removeToken',
		});
	}
	await Users.removePersonalAccessTokenOfUser({
		userId,
		loginTokenObject: {
			type: 'personalAccessToken',
			name: tokenName,
		},
	});
};

Meteor.methods<ServerMethods>({
	'personalAccessTokens:removeToken': twoFactorRequired(async function ({ tokenName }: { tokenName: string }) {
		const uid = Meteor.userId();
		if (!uid) {
			throw new Meteor.Error('not-authorized', 'Not Authorized', {
				method: 'personalAccessTokens:removeToken',

View on GitHub (pinned to b2c16d5842)