RocketChat/Rocket.Chat · error

You are the last owner. Please set new owner before banning

Error message

You are the last owner. Please set new owner before banning the user.

What it means

The target holds the 'owner' role in this room and Roles.countUsersInRole('owner', room._id) === 1 - banning them would orphan the room, so the server refuses until another owner exists. This protects channels and private groups from becoming ownerless; the message text tells the moderator exactly what to do.

Source

Thrown at apps/meteor/server/lib/banUserFromRoom.ts:53

	const subscription = await Subscriptions.findOneByRoomIdAndUserId(data.rid, bannedUser._id, {
		projection: { _id: 1, status: 1 },
	});
	if (!subscription) {
		throw new Error('User is not in this room');
	}

	// Cannot ban a user who is already banned
	if (isBannedSubscription(subscription)) {
		throw new Error('User is already banned from this room');
	}

	// Cannot ban the last owner
	if (await hasRoleAsync(bannedUser._id, 'owner', room._id)) {
		const numOwners = await Roles.countUsersInRole('owner', room._id);

		if (numOwners === 1) {
			throw new Error('You are the last owner. Please set new owner before banning the user.');
		}
	}

	await banUserFromRoom(data.rid, bannedUser, fromUser);

	return true;
};

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Promote another member to owner first (channels.addOwner / groups.addOwner with roomId and userId), then retry the ban
  2. Or have the owner transfer ownership and step out of the room before any ban
  3. Surface the actionable message ('set new owner before banning') directly in the moderation UI

Example fix

// before
await POST '/api/v1/rooms.banUser' { roomId, username: 'last.owner' }; // throws

// after
await POST '/api/v1/channels.addOwner' { roomId, userId: otherMemberId }; // or groups.addOwner for private rooms
await POST '/api/v1/rooms.banUser' { roomId, username: 'last.owner' };
Defensive patterns

Strategy: validation

Validate before calling

const { roles } = await GET '/api/v1/channels.roles' { roomId }; // or groups.roles
const owners = roles.filter((r) => r.roles.includes('owner'));
if (owners.length === 1 && owners[0].u.username === username) {
  // promote another member first (channels.addOwner) before banning
}

Type guard

const isSoleOwner = (roles: { u: { username: string }; roles: string[] }[], username: string): boolean =>
  roles.filter((r) => r.roles.includes('owner')).length === 1 &&
  roles.some((r) => r.roles.includes('owner') && r.u.username === username);

Try / catch

try {
  await POST '/api/v1/rooms.banUser' { roomId, username };
} catch (e) {
  if (String(e.message).includes('last owner')) {
    // run addOwner for another member, then retry the ban once
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Banning the sole owner of a channel; the owners list shrank (other owners left or transferred) making the target the last one; /ban against a room creator who never promoted anyone else.

Common situations: Cleaning up inactive creator accounts; reorganizing room ownership during team migrations.

Related errors


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