{"record":{"id":"44aa4fef33359cdc","repo":"RocketChat/Rocket.Chat","slug":"user-must-have-a-username-to-be-banned-from-the-ro","errorCode":null,"errorMessage":"User must have a username to be banned from the room","messagePattern":"User must have a username to be banned from the room","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/rooms/banUserFromRoom.ts","lineNumber":23,"sourceCode":"\nimport { afterBanFromRoomCallback } from '../callbacks/afterBanFromRoomCallback';\nimport { notifyOnRoomChangedById, notifyOnSubscriptionChanged } from '../notifyListener';\nimport { removeUserFromRolesAsync } from '../roles/removeUserFromRoles';\n\n/**\n * Bans a user from a room when triggered by federation or other external events.\n * Executes only the necessary database operations, with no callbacks, to prevent\n * propagation loops during external event processing.\n * `byUser` must be the Rocket.Chat user who initiated the ban (local record).\n */\nexport const performUserBan = async function (room: IRoom, user: IUser, byUser: IUser): Promise<void> {\n\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);\n\tif (!subscription) {\n\t\treturn;\n\t}\n\n\tif (!user.username) {\n\t\tthrow new Error('User must have a username to be banned from the room');\n\t}\n\n\t// Already banned — nothing to do\n\tif (isBannedSubscription(subscription)) {\n\t\treturn;\n\t}\n\n\t// Set subscription status to BANNED (keeps the record, unlike kick which deletes it)\n\tawait Subscriptions.banByRoomIdAndUserId(room._id, user._id);\n\n\t// Remove the room from the user's __rooms array so they don't appear in member listings\n\tawait Users.removeRoomByUserId(user._id, room._id);\n\n\t// Decrement the room's user count\n\tawait Rooms.incUsersCountById(room._id, -1);\n\n\t// Remove room-scoped roles (moderator, owner, leader)\n\tif (['c', 'p'].includes(room.t)) {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/rooms/banUserFromRoom.ts#L5-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"LDAP/SAML field mapping not producing a username; users imported without usernames; moderation UI allowing actions on incomplete records.","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."],"exampleFix":"// before\nawait banUserFromRoom(rid, user, byUser); // throws if user.username is empty\n\n// after\nif (user.username) {\n  await banUserFromRoom(rid, user, byUser);\n} else {\n  // set a username first, or reject the record\n}","handlingStrategy":"type-guard","validationCode":"if (!user.username) {\n  // set a username (users.update) or reject the record before banning\n}","typeGuard":"const hasUsername = (u: IUser): u is IUser & { username: string } =>\n  typeof u.username === 'string' && u.username.trim().length > 0;\n\nif (hasUsername(user)) {\n  await banUserFromRoom(rid, user, byUser);\n}","tryCatchPattern":"try {\n  await performUserBan(room, user, byUser);\n} catch (error: any) {\n  if (error?.message === 'User must have a username to be banned from the room') {\n    // repair the user record (set username), then retry once\n  }\n}","preventionTips":["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."],"tags":["rooms","moderation","users","username"],"backgroundTag":"missing-username","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}