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

regeneratePersonalAccessTokenOfUser requires an existing token: Users.findPersonalAccessTokenByTokenNameAndUserId({ userId, tokenName }) must return a record whose name matches, otherwise error-token-does-not-exists is thrown. The existing token's bypassTwoFactwoFactor flag is carried over to the regenerated one.

Solutions

  1. List the user's tokens and confirm the exact name (case-sensitive) before regenerating.
  2. If the token was removed, create it again with personalAccessTokens:generateToken.
  3. Avoid concurrent remove+regenerate races for the same token name.

Example fix

// before
await Meteor.callAsync('personalAccessTokens:regenerateToken', { tokenName: 'ci-deploy ' }); // trailing space

// after
const exists = await Users.findPersonalAccessTokenByTokenNameAndUserId({ userId: uid, tokenName: 'ci-deploy' });
if (!exists) throw new Error('token missing: create it first with generateToken');
await Meteor.callAsync('personalAccessTokens:regenerateToken', { tokenName: 'ci-deploy' });
Defensive patterns

Strategy: validation

Validate before calling

const token = await Users.findPersonalAccessTokenByTokenNameAndUserId({ userId, tokenName });
if (!token) {
	// nothing to rotate: create it with generateToken first
}

Try / catch

try {
	await Meteor.callAsync('personalAccessTokens:regenerateToken', { tokenName });
} catch (e: any) {
	if (e?.error === 'error-token-does-not-exists') {
		await Meteor.callAsync('personalAccessTokens:generateToken', { tokenName, bypassTwoFactor: false });
	} else throw e;
}

Prevention

When it happens

Trigger: Calling personalAccessTokens:regenerateToken for a name that was never created, was already removed (including a concurrent remove), or is misspelled/differently cased.

Common situations: Rotating a token after someone deleted it, scripts referencing retired token names, name typos.

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/6a9fc9ff3a15d48f. Report an issue: GitHub.

Appendix: source

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

	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		'personalAccessTokens:regenerateToken'(params: { tokenName: string }): Promise<string>;
	}
}

export const regeneratePersonalAccessTokenOfUser = async (tokenName: string, userId: string): Promise<string> => {
	if (!(await hasPermissionAsync(userId, 'create-personal-access-tokens'))) {
		throw new Meteor.Error('not-authorized', 'Not Authorized', {
			method: 'personalAccessTokens:regenerateToken',
		});
	}

	const tokenExist = await Users.findPersonalAccessTokenByTokenNameAndUserId({
		userId,
		tokenName,
	});
	if (!tokenExist) {
		throw new Meteor.Error('error-token-does-not-exists', 'Token does not exist', {
			method: 'personalAccessTokens:regenerateToken',
		});
	}

	await removePersonalAccessTokenOfUser(tokenName, userId);

	const tokenObject = tokenExist.services?.resume?.loginTokens?.find((token) => isPersonalAccessToken(token) && token.name === tokenName);

	return generatePersonalAccessTokenOfUser({
		tokenName,
		userId,
		bypassTwoFactor: (tokenObject && isPersonalAccessToken(tokenObject) && tokenObject.bypassTwoFactor) || false,
	});
};

Meteor.methods<ServerMethods>({
	'personalAccessTokens:regenerateToken': twoFactorRequired(async function ({ tokenName }: { tokenName: string }) {
		const uid = Meteor.userId();

View on GitHub (pinned to b2c16d5842)