{"record":{"id":"e0c8d0abf82410bc","repo":"RocketChat/Rocket.Chat","slug":"error-not-authorized-e0c8d0","errorCode":"error-not-authorized","errorMessage":"error-not-authorized","messagePattern":"error-not-authorized","errorType":"error_code","errorClass":"Error","httpStatus":403,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/closeLivechatRoom.ts","lineNumber":39,"sourceCode":"\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,\n\t\t\t\t\t\t\t\tsubject: transcriptEmail.requestData.subject,\n\t\t\t\t\t\t\t\trequestedAt: new Date(),\n\t\t\t\t\t\t\t\trequestedBy: user,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/closeLivechatRoom.ts#L21-L57","documentation":"Before closing an omnichannel room, closeLivechatRoom checks that the closing user either has a subscription in that room or holds the 'close-others-livechat-room' permission (checked asynchronously via hasPermissionAsync); otherwise it throws Error('error-not-authorized'). This guards against users closing chats they are not participating in.","triggerScenarios":"A livechat manager or admin without 'close-others-livechat-room' calls closeLivechatRoom on a room they never served; a bot/integration user closes rooms it has no subscription for; the closing user id belongs to a different workspace.","commonSituations":"Custom roles cloned from agent that lost the permission after an upgrade reshuffled role definitions; bulk-close scripts running as a service user with no room subscriptions; permissions removed during an admin audit.","solutions":["Grant 'close-others-livechat-room' to the role of any user who must close other agents' chats","Close the room as its serving agent (the user in room.servedBy), who has a subscription","Invoke the close API with a user that actually participated in the room","Re-audit role-permission sets after upgrades so omnichannel close permissions survive"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { Subscriptions } from '@rocket.chat/models';\nimport { hasPermissionAsync } from '../../../authorization/server';\n\n// Can this user close this room?\nconst sub = await Subscriptions.findOneByRoomIdAndUserId(roomId, user._id, { projection: { _id: 1 } });\nconst allowed = !!sub || (await hasPermissionAsync(user._id, 'close-others-livechat-room'));\nif (!allowed) {\n  // close as the serving agent instead, or grant the permission first\n}","typeGuard":null,"tryCatchPattern":"try {\n  await closeLivechatRoom(roomId, user, { clientAction: true });\n} catch (err: any) {\n  if (err?.message === 'error-not-authorized') return respondForbidden('close-others-livechat-room required');\n  throw err;\n}","preventionTips":["Grant 'close-others-livechat-room' to livechat-manager roles that must close other agents' chats","Run automated close flows as the room's serving agent","Re-audit role permission sets after major upgrades"],"tags":["omnichannel","livechat","permissions","authorization"],"backgroundTag":"insufficient-permissions","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}