RocketChat/Rocket.Chat · error · Meteor.Error
error-token-already-exists
error-token-already-exists
Error message
A token with this name already exists
What it means
Thrown by generatePersonalAccessTokenOfUser when Users.findPersonalAccessTokenByTokenNameAndUserId returns a record for that (userId, tokenName) pair. Personal access token names must be unique per user, so the duplicate check blocks the create. Token name uniqueness is enforced at the application layer before any insert.
Source
Thrown at apps/meteor/imports/personal-access-tokens/server/api/methods/generateToken.ts:37
userId,
}: {
tokenName: string;
userId: string;
bypassTwoFactor: boolean;
}): Promise<string> => {
if (!(await hasPermissionAsync(userId, 'create-personal-access-tokens'))) {
throw new Meteor.Error('not-authorized', 'Not Authorized', {
method: 'personalAccessTokens:generateToken',
});
}
const token = Random.secret();
const tokenExist = await Users.findPersonalAccessTokenByTokenNameAndUserId({
userId,
tokenName,
});
if (tokenExist) {
throw new Meteor.Error('error-token-already-exists', 'A token with this name already exists', {
method: 'personalAccessTokens:generateToken',
});
}
await Users.addPersonalAccessTokenToUser({
userId,
loginTokenObject: {
hashedToken: Accounts._hashLoginToken(token),
type: 'personalAccessToken',
createdAt: new Date(),
lastTokenPart: token.slice(-6),
name: tokenName,
bypassTwoFactor,
},
});
return token;
};
View on GitHub (pinned to f9d3ec372b)
Solutions
- Choose a different tokenName for the new token.
- If you want to refresh an existing token, call regenerateToken instead of generateToken.
- Remove the existing token first with removeToken, then generate.
- List existing tokens before generating to surface collisions to the user.
Example fix
// before
await generatePersonalAccessTokenOfUser({ userId, tokenName: 'ci-token', bypassTwoFactor: false }); // already exists
// after
await regeneratePersonalAccessTokenOfUser('ci-token', userId); Defensive patterns
Strategy: validation
Validate before calling
async function tokenNameIsFree(userId: string, tokenName: string): Promise<boolean> {
const existing = await Users.findPersonalAccessTokenByTokenNameAndUserId({ userId, tokenName });
return !existing;
} Try / catch
try {
await generatePersonalAccessTokenOfUser({ userId, tokenName, bypassTwoFactor });
} catch (e) {
if (e.error === 'error-token-already-exists') {
// prompt: regenerate existing, or pick a new name
} else throw e;
} Prevention
- List existing token names before letting the user pick one.
- Default to regenerateToken when the name already exists.
- Use unique, descriptive token names in automation to avoid collisions.
When it happens
Trigger: Calling generateToken with a tokenName the user already used; case sensitivity differences are not the cause (names are matched as-is); calling generate when a previous token with the same name exists (even if unused).
Common situations: User re-runs a setup script without removing prior tokens; UI does not refresh the token list so the user retries with the same name; automation picks a generic name like 'ci-token' that already exists.
Related errors
- error-duplicate-role-names-not-allowed
- error-token-does-not-exists
- error-token-does-not-exists
- Invalid Api parameter provided, it must be a valid IApi obje
- Invalid command parameter provided, must be a string.
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/dbcb2ffd5d7b1f09.
Report an issue: GitHub.