{"record":{"id":"2e9bd46c89e4c1a4","repo":"RocketChat/Rocket.Chat","slug":"error-you-are-last-owner-2e9bd4","errorCode":"error-you-are-last-owner","errorMessage":"You are the last owner. Please set new owner before leaving the room.","messagePattern":"You are the last owner\\. Please set new owner before leaving the room\\.","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/rooms/removeUserFromRoom.ts","lineNumber":82,"sourceCode":"\n\tawait Room.beforeUserRemoved(room);\n\n\tif (!canKickAnyUser) {\n\t\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(data.rid, removedUser._id, {\n\t\t\tprojection: { _id: 1 },\n\t\t});\n\t\tif (!subscription) {\n\t\t\tthrow new Meteor.Error('error-user-not-in-room', 'User is not in this room', {\n\t\t\t\tmethod: 'removeUserFromRoom',\n\t\t\t});\n\t\t}\n\t}\n\n\tif (await hasRoleAsync(removedUser._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 Meteor.Error('error-you-are-last-owner', 'You are the last owner. Please set new owner before leaving the room.', {\n\t\t\t\tmethod: 'removeUserFromRoom',\n\t\t\t});\n\t\t}\n\t}\n\n\ttry {\n\t\tawait Apps.self?.triggerEvent(AppEvents.IPreRoomUserLeave, room, removedUser, fromUser);\n\t} catch (error: any) {\n\t\tif (error.name === AppsEngineException.name) {\n\t\t\tthrow new Meteor.Error('error-app-prevented', error.message);\n\t\t}\n\n\t\tthrow error;\n\t}\n\n\tawait callbacks.run('beforeRemoveFromRoom', { removedUser, userWhoRemoved: fromUser }, room);\n\n\tconst deletedSubscription = await Subscriptions.removeByRoomIdAndUserId(data.rid, removedUser._id);","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/removeUserFromRoom.ts#L64-L100","documentation":"Thrown by 'removeUserFromRoom' when the user being removed holds the 'owner' role in the room and a role count shows they are the only owner (Roles.countUsersInRole('owner', room._id) === 1). Rocket.Chat refuses to kick the last owner to prevent rooms becoming ownerless, where nobody could moderate, edit settings, or manage membership. A new owner must be set before this user can be removed.","triggerScenarios":"Kicking the sole owner of a channel/group; demoting other owners first and then attempting to remove the remaining one; automated cleanup scripts that remove all members including the last owner; attempting to kick a team-creator who never transferred ownership.","commonSituations":"Offboarding scripts that purge a workspace admin/owner from every room; admins trying to delete a test room by first kicking its creator; rooms where other owners left over time leaving exactly one.","solutions":["Promote another existing member to owner first (Meteor method 'addUserToRole'/'setOwner', or REST POST /api/v1/channels.addOwner with roleId/permission), then retry the removal.","If the goal is to delete the room entirely, archive/delete the room instead of kicking its last owner.","For self-removal flows, have the owner use leaveRoom after transferring ownership (same rule applies).","In bulk scripts, skip or defer rooms where the target is the last owner, and surface them for manual ownership transfer."],"exampleFix":"// before\nawait removeUserFromRoomMethod(fromId, { rid, username: target }); // target is last owner -> error-you-are-last-owner\n\n// after\nif ((await Roles.countUsersInRole('owner', rid)) === 1 && (await hasRoleAsync(targetId, 'owner', rid))) {\n  await Meteor.callAsync('addUserToRole', 'owner', [otherMemberUsername], rid); // set new owner first\n}\nawait removeUserFromRoomMethod(fromId, { rid, username: target });","handlingStrategy":"validation","validationCode":"// Server-side: ensure the target is not the last owner before kicking\nconst isOwner = await hasRoleAsync(targetId, 'owner', rid);\nconst ownerCount = await Roles.countUsersInRole('owner', rid);\nif (isOwner && ownerCount === 1) {\n  const successor = await Subscriptions.findOneByRoomIdAndUserId(rid, successorId, { projection: { _id: 1 } });\n  if (!successor) throw new Error('Pick an existing member as the new owner');\n  await Meteor.callAsync('addUserToRole', 'owner', [successorUsername], rid);\n}\nawait removeUserFromRoomMethod(fromId, { rid, username: targetUsername });","typeGuard":null,"tryCatchPattern":"try {\n  await Meteor.callAsync('removeUserFromRoom', { rid, username });\n} catch (err) {\n  if (err instanceof Meteor.Error && err.error === 'error-you-are-last-owner') {\n    throw new Error(`Promote another owner for room ${rid} before removing ${username}`);\n  }\n  throw err;\n}","preventionTips":["Check owner role and owner count before attempting removal of privileged members.","In offboarding scripts, collect 'last-owner rooms' for manual transfer instead of failing the whole run.","Prefer transferring ownership (setOwner) as the first step of any owner-removal workflow.","Remember deleting/archiving the room may be the right action instead of kicking its creator."],"tags":["rocket-chat","meteor-method","room-management","ownership","roles"],"backgroundTag":"last-owner-protection","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}