RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-role

error-invalid-role

Error message

Role does not exist

What it means

Thrown by Rocket.Chat's authorization layer when a request attaches a role to a permission but the `role` argument matches no document in the Roles collection. Reached via DDP method 'authorization:addPermissionToRole' or REST 'POST /api/v1/permissions.addRole' (both call addPermissionToRoleMethod). The permission is looked up first, so this error specifically means permissionId was valid but the role id was not.

Source

Thrown at apps/meteor/server/lib/authorization/permissionRole.ts:31

	if (AuthorizationUtils.isPermissionRestrictedForRole(permissionId, role)) {
		throw new Meteor.Error('error-action-not-allowed', 'Permission is restricted', {
			method: 'authorization:addPermissionToRole',
			action: 'Adding_permission',
		});
	}

	const permission = await Permissions.findOneById(permissionId);

	if (!permission) {
		throw new Meteor.Error('error-invalid-permission', 'Permission does not exist', {
			method: 'authorization:addPermissionToRole',
			action: 'Adding_permission',
		});
	}

	if (!(await Roles.findOneById(role, { projection: { _id: 1 } }))) {
		throw new Meteor.Error('error-invalid-role', 'Role does not exist', {
			method: 'authorization:addPermissionToRole',
			action: 'Adding_permission',
		});
	}

	if (
		!(await hasPermissionAsync(uid, 'access-permissions')) ||
		(permission.level === CONSTANTS.SETTINGS_LEVEL && !(await hasPermissionAsync(uid, 'access-setting-permissions')))
	) {
		throw new Meteor.Error('error-action-not-allowed', 'Adding permission is not allowed', {
			method: 'authorization:addPermissionToRole',
			action: 'Adding_permission',
		});
	}

	if (permission.groupPermissionId) {
		await Permissions.addRole(permission.groupPermissionId, role);
		void notifyOnPermissionChangedById(permission.groupPermissionId);

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Re-fetch the current role list (GET /api/v1/roles.list or reload Administration > Permissions) and pass the live role _id, not its name or description
  2. If the role was deleted unintentionally, recreate it under Administration > Roles and retry
  3. Guard the call by verifying the role exists first (see validation code)
  4. In automation, resolve role ids at runtime instead of hardcoding them

Example fix

// before
await POST '/api/v1/permissions.addRole' { permissionId: 'ban-user', role: 'moderator' } // 'moderator' was deleted

// after
const role = (await GET '/api/v1/roles.list').roles.find((r) => r._id === 'moderator');
if (!role) throw new Error('Role was deleted - recreate it first');
await POST '/api/v1/permissions.addRole' { permissionId: 'ban-user', role: role._id };
Defensive patterns

Strategy: validation

Validate before calling

const res = await fetch('/api/v1/roles.list', { headers: { 'X-Auth-Token': token, 'X-User-Id': uid } }).then((r) => r.json());
if (!res.roles.some((r) => r._id === roleId)) {
  // refresh role list / recreate role instead of calling permissions.addRole
}

Type guard

const isRoleRef = (r: unknown): r is { _id: string; name?: string } =>
  typeof r === 'object' && r !== null && typeof (r as { _id?: unknown })._id === 'string';

Try / catch

try {
  await call('authorization:addPermissionToRole', permissionId, roleId);
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-invalid-role') {
    // refresh roles and re-prompt the admin
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling permissions.addRole with the _id of a role that was deleted (e.g. a custom role removed by another admin); submitting from a stale Permissions admin screen; passing a role name/description where the role _id is expected; hardcoding a role id from another workspace or seed data that does not exist on this server.

Common situations: Two admins editing permissions concurrently (one deletes the role while the other's browser holds the old list); automation scripts provisioning permissions on a fresh install; workspaces restored from backup where custom roles were not migrated; role rename creating a new _id and invalidating stored references.

Related errors


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