{"record":{"id":"91193bfbce2ef73a","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-scope","errorCode":"error-invalid-scope","errorMessage":"Invalid scope","messagePattern":"Invalid scope","errorType":"exception","errorClass":"MeteorError","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/lib/roles/insertRole.ts","lineNumber":20,"sourceCode":"import type { IRole } from '@rocket.chat/core-typings';\nimport { Roles } from '@rocket.chat/models';\n\nimport { isValidRoleScope } from '../../../../lib/roles/isValidRoleScope';\nimport { notifyOnRoleChanged } from '../../../../server/lib/notifyListener';\n\ntype InsertRoleOptions = {\n\tbroadcastUpdate?: boolean;\n};\n\nexport const insertRoleAsync = async (roleData: Omit<IRole, '_id' | '_updatedAt'>, options: InsertRoleOptions = {}): Promise<IRole> => {\n\tconst { name, scope, description, mandatory2fa } = roleData;\n\n\tif (await Roles.findOneByName(name)) {\n\t\tthrow new MeteorError('error-duplicate-role-names-not-allowed', 'Role name already exists');\n\t}\n\n\tif (!isValidRoleScope(scope)) {\n\t\tthrow new MeteorError('error-invalid-scope', 'Invalid scope');\n\t}\n\n\tconst role = await Roles.createWithRandomId(name, scope, description, false, mandatory2fa);\n\n\tvoid notifyOnRoleChanged(role);\n\n\tif (options.broadcastUpdate) {\n\t\tvoid api.broadcast('user.roleUpdate', {\n\t\t\ttype: 'changed',\n\t\t\t_id: role._id,\n\t\t});\n\t}\n\n\treturn role;\n};\n","sourceCodeStart":2,"sourceCodeEnd":36,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/lib/roles/insertRole.ts#L2-L36","documentation":"Thrown by insertRoleAsync in insertRole.ts:20 when isValidRoleScope(scope) is false. Valid scopes are exactly 'Users' or 'Subscriptions' (see isValidRoleScope.ts). MeteorError code 'error-invalid-scope'.","triggerScenarios":"Passing a scope that is not in ['Users','Subscriptions'] — e.g. undefined, null, 'Global', 'Rooms', or a custom string.","commonSituations":"Caller omits scope assuming a default; custom integration assumes a wider scope enum; typo in scope value.","solutions":["Set scope to 'Users' or 'Subscriptions' explicitly.","Validate scope against ['Users','Subscriptions'] before calling insertRoleAsync.","Catch MeteorError 'error-invalid-scope' and prompt for a valid scope."],"exampleFix":"// before\nawait insertRoleAsync({ name, scope: 'Global', description });\n\n// after\nconst VALID = ['Users', 'Subscriptions'] as const;\nconst scope = VALID.includes(rawScope) ? rawScope : 'Users';\nawait insertRoleAsync({ name, scope, description });","handlingStrategy":"validation","validationCode":"import { isValidRoleScope } from '../../../../lib/roles/isValidRoleScope';\n// or inline:\nconst VALID = ['Users', 'Subscriptions'] as const;\nif (!VALID.includes(scope)) throw new Error('invalid scope');","typeGuard":"const isValidScope = (scope: unknown): scope is 'Users' | 'Subscriptions' =>\n  scope === 'Users' || scope === 'Subscriptions';","tryCatchPattern":"try { await insertRoleAsync(roleData); }\ncatch (e) {\n  if (e?.code === 'error-invalid-scope') { /* re-prompt */ return; }\n  throw e;\n}","preventionTips":["Always pass scope explicitly from the enum.","Validate scope at the form/API boundary."],"tags":["roles","validation","meteor-error"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}