{"record":{"id":"4aca06553d71a6e2","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-room-4aca06","errorCode":"error-invalid-room","errorMessage":"Invalid room","messagePattern":"Invalid room","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/rooms/addRoomOwner.ts","lineNumber":30,"sourceCode":"import { notifyOnSubscriptionChangedById } from '../../lib/notifyListener';\nimport { syncRoomRolePriorityForUserAndRoom } from '../../lib/roles/syncRoomRolePriority';\nimport { isFederationEnabled, FederationMatrixInvalidConfigurationError } from '../../services/federation/utils';\nimport { settings } from '../../settings';\n\ndeclare module '@rocket.chat/ddp-client' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\taddRoomOwner(rid: IRoom['_id'], userId: IUser['_id']): boolean;\n\t}\n}\n\nexport const addRoomOwner = async (fromUserId: IUser['_id'], rid: IRoom['_id'], userId: IUser['_id']): Promise<boolean> => {\n\tcheck(rid, String);\n\tcheck(userId, String);\n\n\tconst room = await Rooms.findOneById(rid, { projection: { t: 1, federated: 1, federation: 1 } });\n\tif (!room) {\n\t\tthrow new Meteor.Error('error-invalid-room', 'Invalid room', {\n\t\t\tmethod: 'addRoomOwner',\n\t\t});\n\t}\n\n\tconst isFederated = isRoomFederated(room);\n\n\tif (!(await hasPermissionAsync(fromUserId, 'set-owner', rid)) && !isFederated) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', {\n\t\t\tmethod: 'addRoomOwner',\n\t\t});\n\t}\n\n\tif (isFederated && !isFederationEnabled()) {\n\t\tthrow new FederationMatrixInvalidConfigurationError('unable to change room owners');\n\t}\n\n\tconst user = await Users.findOneById(userId);\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/addRoomOwner.ts#L12-L48","documentation":"Thrown by addRoomOwner() in apps/meteor/server/meteor-methods/rooms/addRoomOwner.ts:30 when Rooms.findOneById(rid) returns null — no room document matches the supplied room ID. The lookup only projects t/federated/federation, so the ID must exist as a room _id. It fires before any permission or federation checks, making 'room does not exist' the first gate of the operation.","triggerScenarios":"Calling addRoomOwner / the 'addRoomOwner' Meteor method / flows that reuse it with a rid that is not a room _id (e.g. a subscription _id, a message rid typo, an ID from another workspace, or a room that was deleted). Also triggered by stale rid values cached in client code after the room was removed.","commonSituations":"Copy-pasting the wrong ObjectId from the database; referencing a deleted channel; environment mismatch (dev rid used against prod); federation scenarios where the remote room ID format differs; client code holding a rid across room deletion.","solutions":["Verify the rid exists: on the server await Rooms.findOneById(rid, { projection: { _id: 1 } }); on the client call the rooms API to confirm the room is still available.","Re-fetch the rid at the point of use (e.g. from the current subscription/room record) instead of caching it long-term.","Confirm you are on the correct workspace/environment for that room ID.","Prefer the REST endpoints POST /v1/channels.addOwner / POST /v1/groups.addOwner, which return structured 400 invalid-room responses."],"exampleFix":"// before\nawait addRoomOwner(uid, '665f0c1e2f7ba1a4b9a2c111', userId);\n\n// after\nconst room = await Rooms.findOneById(rid, { projection: { _id: 1 } });\nif (!room) throw new Error(`room ${rid} not found; refresh rid`);\nawait addRoomOwner(uid, room._id, userId);","handlingStrategy":"validation","validationCode":"const room = await Rooms.findOneById(rid, { projection: { _id: 1 } });\nif (!room) throw new Error(`room ${rid} not found`);","typeGuard":"const isRoomId = (v: unknown): v is string => typeof v === 'string' && /^[A-Za-z0-9]{17}$/.test(v);","tryCatchPattern":"try {\n  await addRoomOwner(uid, rid, userId);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-invalid-room') {\n    // refresh rid from the current room/subscription context\n  }\n}","preventionTips":["Always resolve rid from a live room/subscription document rather than persisted strings.","Validate IDs at the API boundary (type + format) before they reach method calls.","Prefer REST addOwner endpoints for clearer error bodies."],"tags":["meteor-method","rooms","invalid-id","validation"],"backgroundTag":"room-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}