RocketChat/Rocket.Chat · warning

User is already banned from this room

Error message

User is already banned from this room

What it means

The target's subscription already has status 'BANNED' (isBannedSubscription checks subscription.status === 'BANNED'), so re-banning is rejected. Ban state lives on the subscription document; rooms.unbanUser resets it. For callers wanting the user banned, this error means the desired state already holds.

Source

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

	if (!(await canAccessRoomAsync(room, fromUser))) {
		throw new Error('The required "roomId" or "roomName" param provided does not match any group');
	}

	const bannedUser = await Users.findOneByUsernameIgnoringCase(data.username);
	if (!bannedUser) {
		throw new Error('User not found');
	}

	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. Treat the error as success (target state already holds), or call rooms.unbanUser first if a re-ban is intended
  2. Make the UI idempotent: disable the ban action for members already banned
  3. Dedupe retries on the client before resubmitting

Example fix

// before
await POST '/api/v1/rooms.banUser' { roomId, username }; // throws if already banned

// after
try {
  await POST '/api/v1/rooms.banUser' { roomId, username };
} catch (e) {
  if (!String(e.message).includes('already banned')) throw e;
  // already in target state - ok
}
Defensive patterns

Strategy: try-catch

Validate before calling

// if member state is visible in your client, check it first:
if (member.status === 'BANNED' /* or subscription status */) {
  // already banned - no call needed
}

Type guard

import { isBannedSubscription } from '@rocket.chat/core-typings';
// server-side narrowing: (s: ISubscription): s is IBannedSubscription

Try / catch

try {
  await POST '/api/v1/rooms.banUser' { roomId, username };
} catch (e) {
  if (String(e.message).includes('already banned')) {
    // idempotent success - target state already holds
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Double-click or double-submit of the ban action; banning a user already banned by another moderator; retrying after a client timeout when the first call actually succeeded.

Common situations: Non-idempotent moderation UIs; concurrent moderators acting on the same member; at-least-once API clients retrying blindly.

Related errors


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