RocketChat/Rocket.Chat · error · Meteor.Error

error-role-in-use

error-role-in-use

Error message

Cannot delete role because it's in use

What it means

Thrown by POST /api/v1/roles.delete when Roles.countUsersInRole(role._id) is greater than zero — users (or room-scoped assignments) still reference the role. Referential integrity requires the role to be empty before removal; this is the last guard, after existence and protected checks pass.

Solutions

  1. List members first: GET /api/v1/roles.getUsersInRole?role=<id> to see who holds it
  2. Remove them: POST /api/v1/roles.removeUserFromRole { roleId, username, roomId? } for each (remember room-scoped grants need the roomId)
  3. Retry roles.delete only after the users list comes back empty

Example fix

// before
await sdk.post('roles.delete', { roleId });

// after (drain members, then delete)
const { users } = await sdk.get('roles.getUsersInRole', { role: roleId, count: 0 });
for (const u of users) await sdk.post('roles.removeUserFromRole', { roleId, username: u.username });
await sdk.post('roles.delete', { roleId });
Defensive patterns

Strategy: validation

Validate before calling

// confirm the role is empty before attempting deletion
const { total } = await sdk.get('roles.getUsersInRole', { role: role._id, count: 1 });
if (total > 0) throw new Error(`role still has ${total} assignee(s) — remove them first`);
await sdk.post('roles.delete', { roleId: role._id });

Try / catch

catch 'error-role-in-use', fetch members via roles.getUsersInRole, remove each with roles.removeUserFromRole (passing roomId for room-scoped grants), then retry the delete; treat repeated failure as leftover room-scoped assignments.

Prevention

When it happens

Trigger: POST /api/v1/roles.delete on a custom role that still has members — e.g. an onboarding role granted to every new user, or a room-scoped role still assigned inside channels. The role exists, is not protected, but countUsersInRole returns > 0.

Common situations: Decommissioning a department role while staff still hold it; forgetting room-scoped assignments (moderator in a channel counts); bulk scripts deleting roles before unassigning them.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/c4898f7d362d5c96. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/server/api/v1/roles.ts:247

				401: validateUnauthorizedErrorResponse,
				403: validateForbiddenErrorResponse,
			},
		},
		async function action() {
			const { bodyParams } = this;

			const role = await Roles.findOneByIdOrName(bodyParams.roleId);

			if (!role) {
				throw new Meteor.Error('error-invalid-roleId', 'This role does not exist');
			}

			if (role.protected) {
				throw new Meteor.Error('error-role-protected', 'Cannot delete a protected role');
			}

			if ((await Roles.countUsersInRole(role._id)) > 0) {
				throw new Meteor.Error('error-role-in-use', "Cannot delete role because it's in use");
			}

			await Roles.removeById(role._id);

			void notifyOnRoleChanged(role, 'removed');

			return API.v1.success();
		},
	)
	.post(
		'roles.removeUserFromRole',
		{
			authRequired: true,
			permissionsRequired: ['access-permissions'],
			body: isRoleRemoveUserFromRoleProps,
			response: {
				200: ajv.compile<{ role: IRole }>({
					type: 'object',

View on GitHub (pinned to b2c16d5842)