{"record":{"id":"16ee1c69bff85c2f","repo":"RocketChat/Rocket.Chat","slug":"error-not-allowed-16ee1c","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/rooms/getRoomById.ts","lineNumber":29,"sourceCode":"\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\tgetRoomById(rid: IRoom['_id']): IRoom;\n\t}\n}\n\nMeteor.methods<ServerMethods>({\n\tasync getRoomById(rid) {\n\t\tcheck(rid, String);\n\t\tconst userId = Meteor.userId();\n\t\tif (!userId) {\n\t\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\t\tmethod: 'getRoomNameById',\n\t\t\t});\n\t\t}\n\n\t\tconst room = await Rooms.findOneById(rid);\n\t\tif (room == null) {\n\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', {\n\t\t\t\tmethod: 'getRoomNameById',\n\t\t\t});\n\t\t}\n\t\tif (!(await canAccessRoomAsync(room, (await Meteor.userAsync()) as IUser))) {\n\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', {\n\t\t\t\tmethod: 'getRoomById',\n\t\t\t});\n\t\t}\n\t\treturn room;\n\t},\n});\n\nDDPRateLimiter.addRule(\n\t{\n\t\ttype: 'method',\n\t\tname: 'getRoomById',\n\t\tuserId() {\n\t\t\treturn true;","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/getRoomById.ts#L11-L47","documentation":"getRoomById maps a missing room to 'error-not-allowed' instead of a dedicated not-found code: Rooms.findOneById(rid) returned null, so no room document exists with that _id. Because the same code is reused at line 34 for real access denial, this error alone cannot distinguish 'no such room' from 'no access'.","triggerScenarios":"Meteor.call('getRoomById', rid) with a nonexistent, already-deleted, or mistyped room id. Since check(rid, String) passes for any string, this path specifically means a well-formed id with no matching Rooms document.","commonSituations":"Stale rid persisted in localStorage or a URL from a room that was later deleted; race where the rooms subscription updates after a deletion but UI code still holds the old rid; passing a subscription id or message id where a room id was expected.","solutions":["Re-fetch the rid from a live source (rooms subscription or the /channel/<name> routing) instead of a cached value","Confirm the room exists on the server: db.rooms.findOne({_id: rid})","Handle 'error-not-allowed' as either not-found or no-access: refresh the room list and drop the stale reference","Prefer GET /api/v1/rooms.info?roomId=... which returns a distinguishable not-found response"],"exampleFix":"// before - rid may be stale after the room was deleted\nconst room = await Meteor.callAsync('getRoomById', rid);\n\n// after - treat failure as invalid reference and resync\ntry {\n  const room = await Meteor.callAsync('getRoomById', rid);\n} catch (e) {\n  if (e?.error === 'error-not-allowed') {\n    await refreshRoomList(); // drop stale rid, reload from server truth\n  }\n}","handlingStrategy":"try-catch","validationCode":"// verify shape and liveness of the rid before the call\nif (typeof rid !== 'string' || rid.length !== 17) throw new Error('malformed room id');\nconst known = RoomManager.getOpenedRoomByRid(rid); // client room cache\nif (!known) throw new Error('unknown room');","typeGuard":null,"tryCatchPattern":"try {\n  const room = await Meteor.callAsync('getRoomById', rid);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-not-allowed') {\n    // ambiguous: room missing OR access denied - resync room list and drop the rid\n    await refreshRooms();\n  }\n}","preventionTips":["Derive rids from live subscriptions rather than persisted caches","Remember 'error-not-allowed' from this method covers not-found too","Prefer /v1/rooms.info when you must distinguish 404 from 403"],"tags":["meteor","ddp","rooms","not-found"],"backgroundTag":"room-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}