{"record":{"id":"a9e498bfe7926a04","repo":"RocketChat/Rocket.Chat","slug":"error-app-prevented-a9e498","errorCode":"error-app-prevented","errorMessage":"error.message","messagePattern":"error\\.message","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/rooms/removeUserFromRoom.ts","lineNumber":106,"sourceCode":" * that should propagate normally to federation and other subscribers.\n */\nexport const removeUserFromRoom = async function (\n\trid: string,\n\tuser: IUser,\n\toptions?: { byUser?: IUser; skipAppPreEvents?: boolean; customSystemMessage?: MessageTypesValues },\n): Promise<void> {\n\tconst room = await Rooms.findOneById(rid);\n\tif (!room) {\n\t\treturn;\n\t}\n\n\t// Rationale: for an abac room, we don't want apps to be able to prevent a user from leaving\n\tif (!options?.skipAppPreEvents) {\n\t\ttry {\n\t\t\tawait Apps.self?.triggerEvent(AppEvents.IPreRoomUserLeave, room, user, options?.byUser);\n\t\t} catch (error: any) {\n\t\t\tif (error.name === AppsEngineException.name) {\n\t\t\t\tthrow new Meteor.Error('error-app-prevented', error.message);\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tawait Room.beforeLeave(room);\n\n\tawait performUserRemoval(room, user, options);\n\n\tawait afterLeaveRoomCallback.run({ user, kicker: options?.byUser }, room);\n\n\tawait Apps.self?.triggerEvent(AppEvents.IPostRoomUserLeave, room, user, options?.byUser);\n};\n","sourceCodeStart":88,"sourceCodeEnd":121,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/rooms/removeUserFromRoom.ts#L88-L121","documentation":"Thrown by removeUserFromRoom when an app's IPreRoomUserLeave event handler vetoes the removal (removeUserFromRoom.ts:106). Apps.self.triggerEvent(AppEvents.IPreRoomUserLeave, room, user, options?.byUser) threw an AppsEngineException, which the server rewraps as Meteor.Error('error-app-prevented', error.message) — the message is whatever the app supplied. Bypassed entirely when options.skipAppPreEvents is set (the ABAC path deliberately skips it so apps cannot trap users in rooms).","triggerScenarios":"An installed Apps-Engine app implements preRoomUserLeave and calls something like throw new AppsEngineException('Cannot leave during onboarding'); then any leaveRoom/kick/removeUser API call on that room throws. Only fires when skipAppPreEvents is not passed.","commonSituations":"Third-party onboarding/gatekeeper apps blocking departures; app updated to enforce membership policies; admin unaware an app vetoes 'leave' actions while debugging why users cannot leave a channel.","solutions":["Identify the vetoing app: check Admin → Apps for apps implementing IPreRoomUserLeave, and read error.message (it is the app's own text)","Disable or reconfigure that app if leaving should be allowed","For internal flows that must proceed regardless (like the ABAC rationale in the code), pass { skipAppPreEvents: true } in the options","If you own the app, restrict the veto to genuinely required cases instead of blocking every leave"],"exampleFix":"// before\nawait removeUserFromRoom(rid, user);\n\n// after (internal flow that must not be vetoed)\nawait removeUserFromRoom(rid, user, { skipAppPreEvents: true });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n\tawait removeUserFromRoom(rid, user, { byUser });\n} catch (e) {\n\tif (e instanceof Meteor.Error && e.error === 'error-app-prevented') {\n\t\t// e.reason is the app's veto message: surface it and point the admin to the app\n\t\tthrow new Meteor.Error('error-app-prevented', `An app prevented leaving: ${e.reason}`);\n\t}\n\tthrow e;\n}","preventionTips":["Audit installed apps for IPreRoomUserLeave handlers when users report they cannot leave rooms","Pass { skipAppPreEvents: true } only for system flows that must not be vetoed (same rationale as the ABAC path)","As an app developer, veto sparingly — blocking leave can trap users"],"tags":["apps-engine","webhook","room-membership","veto","meteor"],"backgroundTag":"app-event-veto","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}