{"record":{"id":"245accf3c37f3c66","repo":"RocketChat/Rocket.Chat","slug":"error-not-allowed-245acc","errorCode":"error-not-allowed","errorMessage":"Not Allowed","messagePattern":"Not Allowed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/rooms.ts","lineNumber":1027,"sourceCode":"\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t},\n\t},\n\tasync function action() {\n\t\tconst { rid, type } = this.bodyParams;\n\n\t\tif (!(await hasPermissionAsync(this.user, 'mail-messages', rid))) {\n\t\t\tthrow new Meteor.Error('error-action-not-allowed', 'Mailing is not allowed');\n\t\t}\n\n\t\tconst room = await Rooms.findOneById(rid);\n\t\tif (!room) {\n\t\t\tthrow new Meteor.Error('error-invalid-room');\n\t\t}\n\n\t\tconst user = await Users.findOneById(this.userId);\n\n\t\tif (!user || !(await canAccessRoomAsync(room, user))) {\n\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not Allowed');\n\t\t}\n\n\t\tif (type === 'file') {\n\t\t\tconst { dateFrom, dateTo } = this.bodyParams;\n\t\t\tconst { format } = this.bodyParams;\n\n\t\t\tconst convertedDateFrom = dateFrom ? new Date(dateFrom) : new Date(0);\n\t\t\tconst convertedDateTo = dateTo ? new Date(dateTo) : new Date();\n\t\t\tconvertedDateTo.setDate(convertedDateTo.getDate() + 1);\n\n\t\t\tif (convertedDateFrom > convertedDateTo) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-dates', 'From date cannot be after To date');\n\t\t\t}\n\n\t\t\tvoid dataExport.sendFile(\n\t\t\t\t{\n\t\t\t\t\trid,\n\t\t\t\t\tformat,","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/rooms.ts#L1009-L1045","documentation":"Thrown by POST /api/v1/rooms.export when the caller has mail-messages permission and the room exists, but the user record is missing or canAccessRoomAsync(room, user) is false: the caller cannot access that room. Typical for private channels, direct messages, and team rooms where the user is not a participant despite holding the export permission.","triggerScenarios":"POST rooms.export with an admin token that has mail-messages but targets a private room that admin is not in (when access checks apply); a bot exporting a DM between two other users; a user removed from a private channel retrying an export.","commonSituations":"Export tooling assumed to be omniscient because it has the permission, only to hit room-access rules; offboarded users' queued exports firing after removal; bots granted broad permissions but never added to private rooms.","solutions":["Run the export as a user who is a member of the target room","Add the bot/user to the room before exporting","Filter export targets to rooms the caller subscribes to (subscriptions.get)","Catch and report 'no access' distinctly from 'room missing'"],"exampleFix":"// before\nawait bot.post('rooms.export', { rid: privateRid, type: 'file' }); // bot not in room\n\n// after\nconst { subscription } = await bot.get('subscriptions.get', { rid: privateRid }).catch(() => ({ subscription: null }));\nif (!subscription) await inviteBotToRoom(privateRid); // or use a member's token\nawait bot.post('rooms.export', { rid: privateRid, type: 'file' });","handlingStrategy":"validation","validationCode":"const { subscription } = await sdk.get('subscriptions.get', { rid }).catch(() => ({ subscription: null }));\nif (!subscription) throw new Error(`caller cannot access room ${rid} — join it or use a member token`);","typeGuard":null,"tryCatchPattern":"try {\n  await sdk.post('rooms.export', { rid, type: 'file' });\n} catch (e: any) {\n  if (e?.response?.data?.errorType === 'error-not-allowed') {\n    // no room access: invite the bot/user, or re-run with a member's credentials\n  }\n  throw e;\n}","preventionTips":["Add export bots as members of the rooms they must cover","Filter export targets by the caller's subscription list","Don't assume mail-messages implies room access"],"tags":["rooms","export","access-control","rest-api"],"backgroundTag":"room-access-denied","analyzedSha":"e4b8178b205510181a96ceefee043d0abcd13e5a","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}