RocketChat/Rocket.Chat · error · Error
User must have a username to be banned from the room
Error message
User must have a username to be banned from the room
What it means
Plain Error thrown by performUserBan when the user record has no username. The ban flow writes system messages and member-list mutations keyed by username, so it refuses to continue for a user without one. Note this path runs for federation-triggered bans and similar external events.
Source
Thrown at apps/meteor/server/lib/rooms/banUserFromRoom.ts:23
import { afterBanFromRoomCallback } from '../callbacks/afterBanFromRoomCallback';
import { notifyOnRoomChangedById, notifyOnSubscriptionChanged } from '../notifyListener';
import { removeUserFromRolesAsync } from '../roles/removeUserFromRoles';
/**
* Bans a user from a room when triggered by federation or other external events.
* Executes only the necessary database operations, with no callbacks, to prevent
* propagation loops during external event processing.
* `byUser` must be the Rocket.Chat user who initiated the ban (local record).
*/
export const performUserBan = async function (room: IRoom, user: IUser, byUser: IUser): Promise<void> {
const subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
if (!subscription) {
return;
}
if (!user.username) {
throw new Error('User must have a username to be banned from the room');
}
// Already banned — nothing to do
if (isBannedSubscription(subscription)) {
return;
}
// Set subscription status to BANNED (keeps the record, unlike kick which deletes it)
await Subscriptions.banByRoomIdAndUserId(room._id, user._id);
// Remove the room from the user's __rooms array so they don't appear in member listings
await Users.removeRoomByUserId(user._id, room._id);
// Decrement the room's user count
await Rooms.incUsersCountById(room._id, -1);
// Remove room-scoped roles (moderator, owner, leader)
if (['c', 'p'].includes(room.t)) {View on GitHub (pinned to b2c16d5842)
Solutions
- Set a username for the user first (admin UI or users.update), then ban.
- Fix the LDAP/SAML/import flow that produced a username-less user.
- Guard the ban action on username presence in callers.
Example fix
// before
await banUserFromRoom(rid, user, byUser); // throws if user.username is empty
// after
if (user.username) {
await banUserFromRoom(rid, user, byUser);
} else {
// set a username first, or reject the record
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!user.username) {
// set a username (users.update) or reject the record before banning
} Type guard
const hasUsername = (u: IUser): u is IUser & { username: string } =>
typeof u.username === 'string' && u.username.trim().length > 0;
if (hasUsername(user)) {
await banUserFromRoom(rid, user, byUser);
} Try / catch
try {
await performUserBan(room, user, byUser);
} catch (error: any) {
if (error?.message === 'User must have a username to be banned from the room') {
// repair the user record (set username), then retry once
}
} Prevention
- Validate LDAP/SAML username mapping at user provisioning time.
- Block moderation actions on records without a username.
- Treat a missing username as a data-quality defect and fix the source.
When it happens
Trigger: banUserFromRoom / performUserBan called for a user whose username is unset or empty: incomplete imports, SAML/LDAP users missing the username mapping, or placeholder federation users.
Common situations: LDAP/SAML field mapping not producing a username; users imported without usernames; moderation UI allowing actions on incomplete records.
Related errors
- Not allowed
- The required "roomId" or "roomName" param provided does not
- User not found
- User is not in this room
- User is already banned from this room
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/44aa4fef33359cdc.
Report an issue: GitHub.