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
- Treat the error as success (target state already holds), or call rooms.unbanUser first if a re-ban is intended
- Make the UI idempotent: disable the ban action for members already banned
- 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
- Make ban actions idempotent: disable them for already-banned members
- Dedupe retries after timeouts before resubmitting
- Call rooms.unbanUser deliberately when a re-ban cycle is intended
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
- User is not in this room
- error-invalid-subscription
- Not allowed
- The required "roomId" or "roomName" param provided does not
- You are the last owner. Please set new owner before banning
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/8380884bfdcc0581.
Report an issue: GitHub.