{"record":{"id":"1983e43e4c034fa0","repo":"RocketChat/Rocket.Chat","slug":"error-not-allowed-1983e4","errorCode":"error-not-allowed","errorMessage":"Not allowed","messagePattern":"Not allowed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/messages/loadNextMessages.ts","lineNumber":35,"sourceCode":"Meteor.methods<ServerMethods>({\n\tasync loadNextMessages(rid, end, limit = 20) {\n\t\tcheck(rid, String);\n\t\tcheck(limit, Number);\n\n\t\tif (!Meteor.userId()) {\n\t\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\t\tmethod: 'loadNextMessages',\n\t\t\t});\n\t\t}\n\n\t\tif (!rid) {\n\t\t\tthrow new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'loadNextMessages' });\n\t\t}\n\n\t\tconst fromId = Meteor.userId();\n\n\t\tif (!fromId || !(await canAccessRoomIdAsync(rid, fromId))) {\n\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'loadNextMessages' });\n\t\t}\n\n\t\tlet records;\n\t\tif (end) {\n\t\t\trecords = await Messages.findVisibleByRoomIdAfterTimestamp(rid, end, true, {\n\t\t\t\tsort: {\n\t\t\t\t\tts: 1,\n\t\t\t\t},\n\t\t\t\tlimit,\n\t\t\t}).toArray();\n\t\t} else {\n\t\t\trecords = await Messages.findVisibleByRoomId(rid, {\n\t\t\t\tsort: {\n\t\t\t\t\tts: 1,\n\t\t\t\t},\n\t\t\t\tlimit,\n\t\t\t}).toArray();\n\t\t}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/messages/loadNextMessages.ts#L17-L53","documentation":"loadNextMessages authorizes via canAccessRoomIdAsync(rid, fromId): if the room does not exist or the logged-in user has no access to it (not a member of the private channel, not a DM participant), it throws error-not-allowed 'Not allowed'. This guard runs after the user and rid checks passed, so hitting it means identity and rid were fine but room access was denied.","triggerScenarios":"Paging newer messages for a room the caller was removed from; a rid of a deleted room (canAccessRoomIdAsync fails); deep links into a private channel the user never joined.","commonSituations":"Stale subscriptions after being kicked; room deleted while the tab stayed open; scripts iterating room ids without respecting membership.","solutions":["Check the Subscriptions cache for rid before calling","Invalidate cached room state on kick/room-deleted events","Catch error-not-allowed and show an inline 'no access' state instead of crashing"],"exampleFix":"// before\nconst { messages } = await Meteor.callAsync('loadNextMessages', rid, end, limit);\n\n// after\nconst sub = Subscriptions.findOne({ rid });\nif (!sub) {\n  return { messages: [] }; // caller has no access to this room\n}\nconst { messages } = await Meteor.callAsync('loadNextMessages', rid, end, limit);","handlingStrategy":"try-catch","validationCode":"const sub = Subscriptions.findOne({ rid });\nif (!sub) {\n  // no membership — skip paging newer messages\n}","typeGuard":null,"tryCatchPattern":"try {\n  const { messages } = await Meteor.callAsync('loadNextMessages', rid, end, limit);\n} catch (error) {\n  if (error instanceof Meteor.Error && error.error === 'error-not-allowed') {\n    return { messages: [] }; // access revoked — stop paging this room\n  }\n  throw error;\n}","preventionTips":["Verify membership via the Subscriptions cache before paging","Stop paging loops when the room disappears from subscriptions","Treat error-not-allowed on history paging as a signal to refresh room state"],"tags":["authorization","room-access","meteor-method"],"backgroundTag":"room-access-denied","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}