{"record":{"id":"54eceee824c501a2","repo":"RocketChat/Rocket.Chat","slug":"error-not-allowed-54ecee","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/getRoomNameById.ts","lineNumber":31,"sourceCode":"\t\tgetRoomNameById(rid: IRoom['_id']): Promise<string | undefined>;\n\t}\n}\n\nMeteor.methods<ServerMethods>({\n\tasync getRoomNameById(rid) {\n\t\tmethodDeprecationLogger.method('getRoomNameById', '9.0.0', '/v1/rooms.info');\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\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\n\t\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, userId, {\n\t\t\tprojection: { _id: 1 },\n\t\t});\n\t\tif (subscription) {\n\t\t\treturn room.name;\n\t\t}\n\n\t\tif (room.t !== 'c' || (await hasPermissionAsync(userId, 'view-c-room')) !== true) {\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\n\t\treturn room.name;","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/getRoomNameById.ts#L13-L49","documentation":"getRoomNameById could not find the room: Rooms.findOneById(rid) returned null, reported as 'error-not-allowed'. Like its sibling getRoomById, this method collapses not-found and not-permitted into the same code, and the id lookup is exact - no name fallback exists here.","triggerScenarios":"Meteor.call('getRoomNameById', rid) with a deleted room id, a mistyped id, or an id for a different entity type; any well-formed string passes check() and reaches the null-room branch.","commonSituations":"Rendering cached notification or favorite lists that outlive the room; ids carried over from another workspace during export/import; UI holding rids collected before a room was archived and deleted.","solutions":["Validate the rid against a current rooms subscription before calling","Check the server directly: db.rooms.findOne({_id: rid})","Handle 'error-not-allowed' by pruning the stale reference from local caches","Migrate to GET /api/v1/rooms.info for a distinguishable not-found signal"],"exampleFix":"// before\nconst name = await Meteor.callAsync('getRoomNameById', rid);\n\n// after - resolve against the live room cache first\nconst cached = RoomManager.getOpenedRoomByRid(rid);\nif (!cached) throw new Error('unknown room');\nconst name = cached.name ?? (await Meteor.callAsync('getRoomNameById', rid));","handlingStrategy":"validation","validationCode":"// confirm the room is present in live state before resolving its name\nif (typeof rid !== 'string' || rid.length !== 17) throw new Error('malformed room id');\nif (!RoomManager.getOpenedRoomByRid(rid)) throw new Error('unknown room');\nconst name = await Meteor.callAsync('getRoomNameById', rid);","typeGuard":null,"tryCatchPattern":"try {\n  const name = await Meteor.callAsync('getRoomNameById', rid);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-not-allowed') {\n    pruneStaleRid(rid); // not-found and no-access share this code\n  }\n}","preventionTips":["Persist room _ids, not derived display data, and revalidate on load","Expect 'error-not-allowed' to mean missing room for this method","Use /v1/rooms.info when 404 vs 403 matters"],"tags":["meteor","ddp","rooms","not-found","deprecated"],"backgroundTag":"room-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}