{"record":{"id":"fc14e357135a6904","repo":"RocketChat/Rocket.Chat","slug":"you-are-the-last-owner-please-set-new-owner-befor","errorCode":null,"errorMessage":"You are the last owner. Please set new owner before banning the user.","messagePattern":"You are the last owner\\. Please set new owner before banning the user\\.","errorType":"exception","errorClass":null,"httpStatus":400,"severity":"error","filePath":"apps/meteor/server/lib/banUserFromRoom.ts","lineNumber":53,"sourceCode":"\n\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(data.rid, bannedUser._id, {\n\t\tprojection: { _id: 1, status: 1 },\n\t});\n\tif (!subscription) {\n\t\tthrow new Error('User is not in this room');\n\t}\n\n\t// Cannot ban a user who is already banned\n\tif (isBannedSubscription(subscription)) {\n\t\tthrow new Error('User is already banned from this room');\n\t}\n\n\t// Cannot ban the last owner\n\tif (await hasRoleAsync(bannedUser._id, 'owner', room._id)) {\n\t\tconst numOwners = await Roles.countUsersInRole('owner', room._id);\n\n\t\tif (numOwners === 1) {\n\t\t\tthrow new Error('You are the last owner. Please set new owner before banning the user.');\n\t\t}\n\t}\n\n\tawait banUserFromRoom(data.rid, bannedUser, fromUser);\n\n\treturn true;\n};\n","sourceCodeStart":35,"sourceCodeEnd":61,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/banUserFromRoom.ts#L35-L61","documentation":"The target holds the 'owner' role in this room and Roles.countUsersInRole('owner', room._id) === 1 - banning them would orphan the room, so the server refuses until another owner exists. This protects channels and private groups from becoming ownerless; the message text tells the moderator exactly what to do.","triggerScenarios":"Banning the sole owner of a channel; the owners list shrank (other owners left or transferred) making the target the last one; /ban against a room creator who never promoted anyone else.","commonSituations":"Cleaning up inactive creator accounts; reorganizing room ownership during team migrations.","solutions":["Promote another member to owner first (channels.addOwner / groups.addOwner with roomId and userId), then retry the ban","Or have the owner transfer ownership and step out of the room before any ban","Surface the actionable message ('set new owner before banning') directly in the moderation UI"],"exampleFix":"// before\nawait POST '/api/v1/rooms.banUser' { roomId, username: 'last.owner' }; // throws\n\n// after\nawait POST '/api/v1/channels.addOwner' { roomId, userId: otherMemberId }; // or groups.addOwner for private rooms\nawait POST '/api/v1/rooms.banUser' { roomId, username: 'last.owner' };","handlingStrategy":"validation","validationCode":"const { roles } = await GET '/api/v1/channels.roles' { roomId }; // or groups.roles\nconst owners = roles.filter((r) => r.roles.includes('owner'));\nif (owners.length === 1 && owners[0].u.username === username) {\n  // promote another member first (channels.addOwner) before banning\n}","typeGuard":"const isSoleOwner = (roles: { u: { username: string }; roles: string[] }[], username: string): boolean =>\n  roles.filter((r) => r.roles.includes('owner')).length === 1 &&\n  roles.some((r) => r.roles.includes('owner') && r.u.username === username);","tryCatchPattern":"try {\n  await POST '/api/v1/rooms.banUser' { roomId, username };\n} catch (e) {\n  if (String(e.message).includes('last owner')) {\n    // run addOwner for another member, then retry the ban once\n  } else {\n    throw e;\n  }\n}","preventionTips":["Check the room's owner list before offering ban on owners","Keep at least two owners in active rooms to avoid the deadlock","Automate promote-then-ban sequences instead of manual retries"],"tags":["rocket-chat","rooms","moderation","ownership","roles"],"backgroundTag":"last-owner-protection","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}