{"record":{"id":"86c15a12d1fb44f1","repo":"RocketChat/Rocket.Chat","slug":"error-room-does-not-exist-86c15a","errorCode":"error-room-does-not-exist","errorMessage":"This room does not exist","messagePattern":"This room does not exist","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/messages/readMessages.ts","lineNumber":31,"sourceCode":"\t\treadMessages(rid: string, readThreads?: boolean): Promise<void>;\n\t}\n}\n\nMeteor.methods<ServerMethods>({\n\tasync readMessages(rid, readThreads = false) {\n\t\tcheck(rid, String);\n\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: 'readMessages',\n\t\t\t});\n\t\t}\n\n\t\tconst user = ((await Meteor.userAsync()) as IUser | null) ?? undefined;\n\t\tconst room = await Rooms.findOneById(rid);\n\t\tif (!room) {\n\t\t\tthrow new Meteor.Error('error-room-does-not-exist', 'This room does not exist', { method: 'readMessages' });\n\t\t}\n\t\tif (!(await canAccessRoomAsync(room, user))) {\n\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'readMessages' });\n\t\t}\n\n\t\tawait readMessages(room, userId, readThreads);\n\t},\n});\n","sourceCodeStart":13,"sourceCodeEnd":40,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/messages/readMessages.ts#L13-L40","documentation":"readMessages resolves rid through Rooms.findOneById; when no room document matches (deleted room, wrong or typo'd id, id from a different workspace), it throws error-room-does-not-exist 'This room does not exist'. This is distinct from the following canAccessRoomAsync failure in the same method, which throws error-not-allowed 'Not allowed' instead.","triggerScenarios":"Meteor.call('readMessages', rid) where rid refers to a room that was deleted, a truncated/copy-pasted id, or a rid from stale local state after the room was removed.","commonSituations":"Mark-as-read effects firing for rooms deleted while the tab was open; deep links with mangled room ids; local caches (IndexedDB, redux persist) holding rids of purged rooms.","solutions":["Verify the room exists in the client's Rooms/Subscriptions cache before calling","Invalidate cached room state when the room-removed event arrives","Catch error-room-does-not-exist and silently drop the read request for gone rooms"],"exampleFix":"// before\nMeteor.call('readMessages', rid);\n\n// after\nconst room = Rooms.findOne({ _id: rid });\nif (!room) {\n  // room no longer exists — drop stale state instead of calling\n} else {\n  Meteor.call('readMessages', rid);\n}","handlingStrategy":"try-catch","validationCode":"const room = RoomsCollection.findOne({ _id: rid });\nif (!room) {\n  // room deleted or unknown — drop stale state instead of calling\n}","typeGuard":null,"tryCatchPattern":"try {\n  await Meteor.callAsync('readMessages', rid, readThreads);\n} catch (error) {\n  if (error instanceof Meteor.Error && error.error === 'error-room-does-not-exist') {\n    // room is gone — clear it from local caches silently\n  } else {\n    throw error;\n  }\n}","preventionTips":["Verify rid against the client Rooms/Subscriptions cache before marking read","Listen for room-removed events and prune persisted caches","Distinguish error-room-does-not-exist from error-not-allowed when handling read failures"],"tags":["room","read-receipts","meteor-method","validation"],"backgroundTag":"room-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}