{"record":{"id":"307d2f3962f1a4d4","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-roleid-307d2f","errorCode":"error-invalid-roleId","errorMessage":"error-invalid-roleId","messagePattern":"error-invalid-roleId","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/roles.ts","lineNumber":200,"sourceCode":"\t\t\t\tusername: 1,\n\t\t\t\temails: 1,\n\t\t\t\tavatarETag: 1,\n\t\t\t\tcreatedAt: 1,\n\t\t\t\t_updatedAt: 1,\n\t\t\t};\n\n\t\t\tif (!role) {\n\t\t\t\tthrow new Meteor.Error('error-param-not-provided', 'Query param \"role\" is required');\n\t\t\t}\n\t\t\tif (roomId && !(await hasPermissionAsync(this.user, 'view-other-user-channels'))) {\n\t\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed');\n\t\t\t}\n\n\t\t\tconst options = { projection: { _id: 1 } };\n\t\t\tconst roleData = await Roles.findOneById<Pick<IRole, '_id'>>(role, options);\n\n\t\t\tif (!roleData) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-roleId');\n\t\t\t}\n\n\t\t\tconst { cursor, totalCount } = await getUsersInRolePaginated(roleData._id, roomId, {\n\t\t\t\tlimit: count,\n\t\t\t\tsort: { username: 1 },\n\t\t\t\tskip: offset,\n\t\t\t\tprojection,\n\t\t\t});\n\n\t\t\tconst [users, total] = await Promise.all([cursor.toArray(), totalCount]);\n\n\t\t\treturn API.v1.success({ users, total });\n\t\t},\n\t)\n\t.post(\n\t\t'roles.delete',\n\t\t{\n\t\t\tauthRequired: true,","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/v1/roles.ts#L182-L218","documentation":"Thrown by GET /api/v1/roles.getUsersInRole when Roles.findOneById(role) returns null. Critically this lookup is by _id only — unlike roles.delete, which accepts id OR name. Passing a human-readable role name like 'admin' or 'moderator' here will always fail with error-invalid-roleId even though the role exists.","triggerScenarios":"GET /api/v1/roles.getUsersInRole?role=admin (a name, not an id); a deleted custom role's id still referenced by cached scripts; a typo'd or truncated role _id.","commonSituations":"Code written against roles.delete (name-friendly) reused for getUsersInRole; role ids hardcoded per environment and stale after a re-install; names and ids conflated in configuration files.","solutions":["Resolve the name to an _id first: GET /api/v1/roles.list returns every role with both fields","Use the 17-char role _id in the role param","If the id came from config, refresh it against roles.list after workspace rebuilds"],"exampleFix":"// before\nawait sdk.get('roles.getUsersInRole', { role: 'admin' }); // name → error\n\n// after\nconst { roles } = await sdk.get('roles.list');\nconst target = roles.find((r) => r.name === 'admin');\nif (!target) throw new Error('unknown role name');\nawait sdk.get('roles.getUsersInRole', { role: target._id });","handlingStrategy":"validation","validationCode":"// resolve to the role's _id before querying users\nconst { roles } = await sdk.get('roles.list');\nconst target = roles.find((r) => r._id === roleParam || r.name === roleParam);\nif (!target) throw new Error(`unknown role: ${roleParam}`);\nawait sdk.get('roles.getUsersInRole', { role: target._id });","typeGuard":"const isRoleId = (v: unknown): v is string =>\n  typeof v === 'string' && /^[A-Za-z0-9]{17}$/.test(v);","tryCatchPattern":"catch 'error-invalid-roleId', re-resolve the param against roles.list (the role may have been renamed/deleted), and retry once with the fresh _id.","preventionTips":["Remember this endpoint matches _id only, unlike roles.delete which also takes names","Cache the roles.list mapping and refresh it after workspace changes","Never hardcode role ids across environments — resolve by name at runtime"],"tags":["roles","not-found","query-params","rest-api"],"backgroundTag":"resource-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}