RocketChat/Rocket.Chat · error · Meteor.Error
error-not-allowed
error-not-allowed
Error message
Not allowed
What it means
Thrown by addRoomOwner() in apps/meteor/server/meteor-methods/rooms/addRoomOwner.ts:38 when the acting user lacks the 'set-owner' permission for that room AND the room is not federated (isRoomFederated(room) === false). It is the authorization gate for granting the 'owner' role; federation is exempted here because Matrix-sourced ownership changes follow a separate path (guarded further down by FederationMatrixInvalidConfigurationError).
Source
Thrown at apps/meteor/server/meteor-methods/rooms/addRoomOwner.ts:38
addRoomOwner(rid: IRoom['_id'], userId: IUser['_id']): boolean;
}
}
export const addRoomOwner = async (fromUserId: IUser['_id'], rid: IRoom['_id'], userId: IUser['_id']): Promise<boolean> => {
check(rid, String);
check(userId, String);
const room = await Rooms.findOneById(rid, { projection: { t: 1, federated: 1, federation: 1 } });
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
method: 'addRoomOwner',
});
}
const isFederated = isRoomFederated(room);
if (!(await hasPermissionAsync(fromUserId, 'set-owner', rid)) && !isFederated) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
method: 'addRoomOwner',
});
}
if (isFederated && !isFederationEnabled()) {
throw new FederationMatrixInvalidConfigurationError('unable to change room owners');
}
const user = await Users.findOneById(userId);
if (!user?.username) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'addRoomOwner',
});
}
const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
View on GitHub (pinned to b2c16d5842)
Solutions
- Grant 'set-owner' to the acting user (globally or scoped to the room) via Administration > Permissions, then retry.
- Verify the permission programmatically before calling: await hasPermissionAsync(fromUserId, 'set-owner', rid).
- Confirm you are passing the intended fromUserId — the check uses fromUserId, not the logged-in user, in the exported helper.
- If the room is federated on purpose but reports as non-federated, verify the room's federation fields were set when it was created.
Example fix
// before
await addRoomOwner(uid, rid, targetUserId);
// after
if (!(await hasPermissionAsync(uid, 'set-owner', rid))) {
throw new Error('missing set-owner permission for this room');
}
await addRoomOwner(uid, rid, targetUserId); Defensive patterns
Strategy: validation
Validate before calling
const canSetOwner = await hasPermissionAsync(uid, 'set-owner', rid);
if (!canSetOwner) throw new Error('missing set-owner permission'); Try / catch
try {
await addRoomOwner(uid, rid, userId);
} catch (e) {
if (e instanceof Meteor.Error && e.error === 'error-not-allowed') {
// surface 'you need set-owner permission' to the user; do not retry
}
} Prevention
- Pre-check hasPermissionAsync(uid, 'set-owner', rid) before enabling the UI action.
- Scope permissions per room when granting set-owner so cross-room abuse is limited.
- In jobs, run as an account that provably holds the needed role.
When it happens
Trigger: A non-admin without 'set-owner' (globally or scoped to the rid) calls 'addRoomOwner'; an admin whose 'set-owner' permission was revoked or scoped to another room; permission changes not yet propagated to the acting session; calling with a fromUserId of a bot/service account that never received the role.
Common situations: Custom role setups where 'set-owner' was removed from the admin role; workspace owners assuming global admin implies per-room permissions after a permission refactor; scripts running as a low-privilege system user; role hierarchies where the target's role priority rules block the action but the permission check fails first.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/d318a2381467304b.
Report an issue: GitHub.