{"record":{"id":"87be16864067da90","repo":"RocketChat/Rocket.Chat","slug":"error-app-prevented-87be16","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/addUserToRoom.ts","lineNumber":75,"sourceCode":"\n\ttry {\n\t\tconst inviterUser = inviter && ((await Users.findOneById(inviter._id)) || undefined);\n\t\t// Not \"duplicated\": we're moving away from callbacks so this is a patch function. We should migrate the next one to be a patch or use this same patch, instead of calling both\n\t\tawait beforeAddUserToRoomPatch([userToBeAdded.username!], room, inviterUser);\n\t\tawait beforeAddUserToRoom.run({ user: userToBeAdded, inviter: inviterUser }, room);\n\t} catch (error) {\n\t\tthrow new Meteor.Error((error as any)?.message);\n\t}\n\n\t// TODO: are we calling this twice?\n\n\tawait callbacks.run('beforeAddedToRoom', { user: userToBeAdded, inviter });\n\n\ttry {\n\t\tawait Apps.self?.triggerEvent(AppEvents.IPreRoomUserJoined, room, userToBeAdded, inviter);\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\t// for federation rooms we stop here since everything else will be handled by the federation invite flow\n\tif (isRoomNativeFederated(room)) {\n\t\treturn;\n\t}\n\n\t// TODO: are we calling this twice?\n\tif (room.t === 'c' || room.t === 'p' || room.t === 'l') {\n\t\t// Add a new event, with an optional inviter\n\t\tawait callbacks.run('beforeAddedToRoom', { user: userToBeAdded, inviter }, room);\n\n\t\t// Keep the current event\n\t\tawait callbacks.run('beforeJoinRoom', userToBeAdded, room);\n\t}","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/rooms/addUserToRoom.ts#L57-L93","documentation":"Meteor.Error('error-app-prevented') thrown when an app's IPreRoomUserJoined handler throws an AppsEngineException during addUserToRoom; the app's message becomes the reason. Non-app errors are rethrown as-is.","triggerScenarios":"An installed app vetoes adding a specific user to a room while addUserToRoom processes the membership add.","commonSituations":"Apps gating joins by approval, reputation, or external policy; app regressions blocking all adds.","solutions":["Read the app-provided message for the veto reason.","Adjust the app's rules or configuration for the affected room/user.","Disable or update the app if the veto is wrong."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await addUserToRoom(rid, user, inviter);\n} catch (error: any) {\n  if (error?.error === 'error-app-prevented') {\n    // error.reason is the app's veto message for IPreRoomUserJoined\n  }\n}","preventionTips":["List apps implementing IPreRoomUserJoined when adds fail unexpectedly.","Keep app join policies configurable per room or role.","Surface the app's reason in moderation UIs."],"tags":["apps-engine","apps","rooms","event-veto"],"backgroundTag":"app-event-prevented","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}