{"record":{"id":"e75f402cd7c94d79","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-room-e75f40","errorCode":"error-invalid-room","errorMessage":"error-invalid-room","messagePattern":"error-invalid-room","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/closeLivechatRoom.ts","lineNumber":34,"sourceCode":"\t\tforceClose = false,\n\t}: {\n\t\tcomment?: string;\n\t\ttags?: string[];\n\t\tgenerateTranscriptPdf?: boolean;\n\t\ttranscriptEmail?:\n\t\t\t| {\n\t\t\t\t\tsendToVisitor: false;\n\t\t\t  }\n\t\t\t| {\n\t\t\t\t\tsendToVisitor: true;\n\t\t\t\t\trequestData: Pick<NonNullable<IOmnichannelRoom['transcriptRequest']>, 'email' | 'subject'>;\n\t\t\t  };\n\t\tforceClose?: boolean;\n\t},\n): Promise<void> => {\n\tconst room = await LivechatRooms.findOneById(roomId);\n\tif (!room) {\n\t\tthrow new Error('error-invalid-room');\n\t}\n\n\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(roomId, user._id, { projection: { _id: 1 } });\n\tif (!subscription && !(await hasPermissionAsync(user, 'close-others-livechat-room'))) {\n\t\tthrow new Error('error-not-authorized');\n\t}\n\n\tconst options: CloseRoomParams['options'] = {\n\t\tclientAction: true,\n\t\ttags,\n\t\t...(generateTranscriptPdf && { pdfTranscript: { requestedBy: user._id } }),\n\t\t...(transcriptEmail && {\n\t\t\t...(transcriptEmail.sendToVisitor\n\t\t\t\t? {\n\t\t\t\t\t\temailTranscript: {\n\t\t\t\t\t\t\tsendToVisitor: true,\n\t\t\t\t\t\t\trequestData: {\n\t\t\t\t\t\t\t\temail: transcriptEmail.requestData.email,","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/closeLivechatRoom.ts#L16-L52","documentation":"closeLivechatRoom loads the room by id from LivechatRooms and throws Error('error-invalid-room') when no document matches. It means the roomId handed to the close flow does not exist in this database at all - it is not the 'already closed' or 'wrong room type' signal (those have their own codes).","triggerScenarios":"Calling closeLivechatRoom (agent close action, REST/method close with a wrong or expired room id), referencing a room from another workspace, or a truncated/typo'd rid in the payload; also possible when a parallel cleanup (e.g. contact removal) deleted the room doc.","commonSituations":"Stale client-side rid after a workspace reset or restore; integrations composing room ids by hand instead of using ids from API responses; environment drift where the client talks to the wrong workspace.","solutions":["Verify the room exists first (LivechatRooms.findOneById or the room info REST endpoint) before closing","Respond with a not-found outcome to the caller - this error is not transient, do not retry","Confirm the client is pointed at the correct workspace/database (URL and credentials)","If a parallel flow may have removed the room, treat 'invalid room' as already-closed for idempotency"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { LivechatRooms } from '@rocket.chat/models';\n\nconst room = await LivechatRooms.findOneById(roomId);\nif (!room) {\n  // do not call closeLivechatRoom - respond 404 or treat as already removed\n}","typeGuard":"import { isOmnichannelRoom } from '@rocket.chat/core-typings';\n\nconst isExistingOmnichannelRoom = (room: any): room is IOmnichannelRoom =>\n  !!room && isOmnichannelRoom(room);","tryCatchPattern":"try {\n  await closeLivechatRoom(roomId, user, { clientAction: true });\n} catch (err: any) {\n  if (err?.message === 'error-invalid-room') return respondNotFound(roomId);\n  throw err;\n}","preventionTips":["Take room ids only from prior API responses, never construct them manually","Validate rid shape/length before calling close endpoints","Design close flows idempotently: a missing room means nothing left to close"],"tags":["omnichannel","livechat","room","not-found"],"backgroundTag":"livechat-room-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}