RocketChat/Rocket.Chat · error · Meteor.Error
error-not-allowed
error-not-allowed
Error message
Not allowed
What it means
addRoomLeader requires the caller to hold the 'set-leader' permission scoped to the room (hasPermissionAsync(fromUserId, 'set-leader', rid)). If the caller's roles lack it globally and for that room, the method throws error-not-allowed before the target user is even loaded. The method is deprecated since 9.0.0 in favor of /v1/channels.addLeader and /v1/groups.addLeader, which enforce the same permission.
Source
Thrown at apps/meteor/server/meteor-methods/rooms/addRoomLeader.ts:26
import { hasPermissionAsync } from '../../lib/authorization/hasPermission';
import { methodDeprecationLogger } from '../../lib/deprecationWarningLogger';
import { notifyOnSubscriptionChangedById } from '../../lib/notifyListener';
import { syncRoomRolePriorityForUserAndRoom } from '../../lib/roles/syncRoomRolePriority';
import { settings } from '../../settings';
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addRoomLeader(rid: IRoom['_id'], userId: IUser['_id']): boolean;
}
}
export const addRoomLeader = async (fromUserId: IUser['_id'], rid: IRoom['_id'], userId: IUser['_id']): Promise<boolean> => {
check(rid, String);
check(userId, String);
if (!(await hasPermissionAsync(fromUserId, 'set-leader', rid))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
method: 'addRoomLeader',
});
}
const user = await Users.findOneById(userId);
if (!user?.username) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'addRoomLeader',
});
}
const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
if (!subscription) {
throw new Meteor.Error('error-user-not-in-room', 'User is not in this room', {
method: 'addRoomLeader',
});View on GitHub (pinned to b2c16d5842)
Solutions
- Grant set-leader to the caller's role globally or for that specific room in Administration > Permissions.
- Use the REST endpoints with a user/token that holds set-leader.
- Catch error-not-allowed and disable the 'Set as leader' UI action for users without the permission.
Defensive patterns
Strategy: try-catch
Validate before calling
// hide 'Set as leader' unless the caller holds set-leader for the room
if (!(await hasPermission('set-leader', rid))) {
// do not offer the action
} Try / catch
try {
await Meteor.callAsync('addRoomLeader', rid, userId);
} catch (e: any) {
if (e?.error === 'error-not-allowed') {
// caller lacks set-leader: surface authorization error, no retry
}
} Prevention
- Check set-leader (global and room scope) before exposing the action.
- Use elevated/admin tokens for role-change automation.
- Remember channel ownership alone does not imply set-leader.
When it happens
Trigger: A non-privileged user calling addRoomLeader, or REST channels.addLeader/groups.addLeader with a token whose user lacks set-leader for that channel/team room.
Common situations: Owners assuming channel-owner rights include set-leader; room-scoped permission overrides removed by admins; custom clients calling the legacy method with a member account.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- error-invalid-user
- error-not-allowed
- error-invalid-role
- The required "roomId" or "roomName" param provided does not
- error-not-allowed
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/9b9f3b08a772d24d.
Report an issue: GitHub.