RocketChat/Rocket.Chat · error · Error
error-user-not-banned
error-user-not-banned
Error message
error-user-not-banned
What it means
After finding the subscription, executeUnbanUserFromRoom checks isBannedSubscription(subscription). If the subscription exists but is neither an invite nor banned (ls/open like a normal member), unban makes no sense and the flow throws Error 'error-user-not-banned'.
Source
Thrown at apps/meteor/server/lib/rooms/executeUnbanUserFromRoom.ts:36
const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
if (!subscription) {
throw new Error('error-invalid-subscription');
}
// if the subscription is an invite it means we were unbanned and then invited again, then
// the invite was accepted and we receive a leave event (meaning the user was unbanned), so
// at this point we just need send the message to say the user was unbanned.
if (isInviteSubscription(subscription)) {
await Message.saveSystemMessage('user-unbanned', rid, user.username, user, {
u: { _id: byUser._id, username: byUser.username },
});
return;
}
// if the subscription exists and is not an invite and not banned
if (!isBannedSubscription(subscription)) {
throw new Error('error-user-not-banned');
}
// Remove the subscription entirely — the user is no longer banned but also not a member.
// Room count and __rooms were already adjusted during ban, so we only delete the document.
await Subscriptions.removeById(subscription._id);
await Message.saveSystemMessage('user-unbanned', rid, user.username, user, {
u: { _id: byUser._id, username: byUser.username },
});
void notifyOnSubscriptionChanged(subscription, 'removed');
void notifyOnRoomChangedById(rid);
const inviterUser = await Users.findOneById(byUser._id);
if (inviterUser) {
await afterUnbanFromRoomCallback.run({ unbannedUser: user, userWhoUnbanned: inviterUser }, room);
}
};View on GitHub (pinned to b2c16d5842)
Solutions
- Pre-check isBannedSubscription before unbanning; skip when the user is not banned
- Refresh moderation state after concurrent unbans so stale UIs do not resubmit
- Serialize ban/unban moderation actions per (rid, userId) to avoid races
Example fix
// before
Meteor.call('unbanUserFromRoom', rid, userId); // may throw error-user-not-banned
// after
const sub = await Subscriptions.findOneByRoomIdAndUserId(rid, userId);
if (!sub || (!isBannedSubscription(sub) && !isInviteSubscription(sub))) return;
Meteor.call('unbanUserFromRoom', rid, userId); Defensive patterns
Strategy: validation
Validate before calling
const sub = await Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
if (sub && !isInviteSubscription(sub) && !isBannedSubscription(sub)) {
// user is a normal active member — nothing to unban
return;
}
await executeUnbanUserFromRoom(rid, user, byUser); Type guard
import { isBannedSubscription } from '@rocket.chat/core-typings';
// subscription has banned/anchor state -> unban is meaningful Try / catch
try {
await executeUnbanUserFromRoom(rid, user, byUser);
} catch (err) {
if (err instanceof Error && err.message === 'error-user-not-banned') {
// stale UI state — refresh the banned user list
}
throw err;
} Prevention
- Refresh banned-user lists from the subscription state before rendering actions
- Treat error-user-not-banned as idempotent success in federation event handlers
- Lock concurrent moderation ops per (rid, userId) to avoid races
When it happens
Trigger: Unbanning a user who is an active member (subscription without ban status), or whose ban marker was cleared by a concurrent unban. The isInviteSubscription branch handled earlier returns without error; only non-invite, non-banned subscriptions reach this throw.
Common situations: Stale moderation UI listing a user as banned after another moderator already unbanned them; permission misconfiguration letting unauthenticated flows call unban; events duplicated by federation or apps.
Related errors
- error-invalid-subscription
- User not subscribed to room
- not-subscribed-room
- error-invalid-subscription
- error-subscription-not-found
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/93c793a750ceaa37.
Report an issue: GitHub.