{"record":{"id":"4cd06381d9ef462f","repo":"RocketChat/Rocket.Chat","slug":"error-token-does-not-exists-4cd063","errorCode":"error-token-does-not-exists","errorMessage":"Token does not exist","messagePattern":"Token does not exist","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/imports/personal-access-tokens/server/api/methods/removeToken.ts","lineNumber":25,"sourceCode":"declare module '@rocket.chat/ddp-client' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\t'personalAccessTokens:removeToken'(params: { tokenName: string }): Promise<void>;\n\t}\n}\n\nexport const removePersonalAccessTokenOfUser = async (tokenName: string, userId: string): Promise<void> => {\n\tif (!(await hasPermissionAsync(userId, 'create-personal-access-tokens'))) {\n\t\tthrow new Meteor.Error('not-authorized', 'Not Authorized', {\n\t\t\tmethod: 'personalAccessTokens:removeToken',\n\t\t});\n\t}\n\tconst tokenExist = await Users.findPersonalAccessTokenByTokenNameAndUserId({\n\t\tuserId,\n\t\ttokenName,\n\t});\n\tif (!tokenExist) {\n\t\tthrow new Meteor.Error('error-token-does-not-exists', 'Token does not exist', {\n\t\t\tmethod: 'personalAccessTokens:removeToken',\n\t\t});\n\t}\n\tawait Users.removePersonalAccessTokenOfUser({\n\t\tuserId,\n\t\tloginTokenObject: {\n\t\t\ttype: 'personalAccessToken',\n\t\t\tname: tokenName,\n\t\t},\n\t});\n};\n\nMeteor.methods<ServerMethods>({\n\t'personalAccessTokens:removeToken': twoFactorRequired(async function ({ tokenName }: { tokenName: string }) {\n\t\tconst uid = Meteor.userId();\n\t\tif (!uid) {\n\t\t\tthrow new Meteor.Error('not-authorized', 'Not Authorized', {\n\t\t\t\tmethod: 'personalAccessTokens:removeToken',","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/imports/personal-access-tokens/server/api/methods/removeToken.ts#L7-L43","documentation":"Thrown by removePersonalAccessTokenOfUser when Users.findPersonalAccessTokenByTokenNameAndUserId returns null — there is no token with that name to remove. The deletion is a no-op only at the DB level; the application treats a missing token as an error so callers know the name was wrong.","triggerScenarios":"Calling removeToken with a tokenName that was already deleted, never existed, or is misspelled; double-submit of a remove action.","commonSituations":"User clicks delete twice; another session already removed it; stale UI list after deletion; typo in the name.","solutions":["Treat the error as success if the goal is simply 'token must not exist' (idempotent remove).","Refresh the token list before allowing a delete action.","Verify the exact tokenName spelling and case.","On the UI, hide the deleted token row immediately to prevent double submits."],"exampleFix":"// before\nawait removePersonalAccessTokenOfUser(tokenName, userId); // throws if already gone\n\n// after\ntry {\n  await removePersonalAccessTokenOfUser(tokenName, userId);\n} catch (e) {\n  if (e.error !== 'error-token-does-not-exists') throw e;\n  // already removed — treat as success\n}","handlingStrategy":"try-catch","validationCode":"async function tokenExists(userId: string, tokenName: string): Promise<boolean> {\n  const t = await Users.findPersonalAccessTokenByTokenNameAndUserId({ userId, tokenName });\n  return Boolean(t);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await removePersonalAccessTokenOfUser(tokenName, userId);\n} catch (e) {\n  if (e.error === 'error-token-does-not-exists') {\n    // treat as success — token is already gone (idempotent remove)\n  } else throw e;\n}","preventionTips":["Make remove actions idempotent by swallowing this specific error when appropriate.","Hide the deleted row immediately in the UI to prevent double submits.","Verify tokenName spelling/case before deleting."],"tags":["personal-access-tokens","not-found","validation"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}