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

  1. Grant 'set-owner' to the acting user (globally or scoped to the room) via Administration > Permissions, then retry.
  2. Verify the permission programmatically before calling: await hasPermissionAsync(fromUserId, 'set-owner', rid).
  3. Confirm you are passing the intended fromUserId — the check uses fromUserId, not the logged-in user, in the exported helper.
  4. 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

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.