{"record":{"id":"a507c984be965c72","repo":"RocketChat/Rocket.Chat","slug":"not-allowed-a507c9","errorCode":"not-allowed","errorMessage":"not-allowed","messagePattern":"not-allowed","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/visitors.ts","lineNumber":182,"sourceCode":");\n\nAPI.v1.addRoute(\n\t'livechat/:rid/messages',\n\t{ authRequired: true, permissionsRequired: ['view-l-room'], validateParams: isLivechatRidMessagesProps },\n\t{\n\t\tasync get() {\n\t\t\tconst { offset, count } = await getPaginationItems(this.queryParams);\n\t\t\tconst { sort } = await this.parseJsonQuery();\n\t\t\tconst { searchTerm } = this.queryParams;\n\n\t\t\tconst room = await LivechatRooms.findOneById(this.urlParams.rid);\n\n\t\t\tif (!room) {\n\t\t\t\tthrow new Error('invalid-room');\n\t\t\t}\n\n\t\t\tif (!(await canAccessRoomAsync(room, this.user))) {\n\t\t\t\tthrow new Error('not-allowed');\n\t\t\t}\n\n\t\t\tconst { cursor, totalCount } = Messages.findLivechatClosedMessages(this.urlParams.rid, searchTerm, {\n\t\t\t\tsort: sort || { ts: -1 },\n\t\t\t\tskip: offset,\n\t\t\t\tlimit: count,\n\t\t\t});\n\n\t\t\tconst [messages, total] = await Promise.all([cursor.toArray(), totalCount]);\n\n\t\t\treturn API.v1.success({\n\t\t\t\tmessages: await normalizeMessagesForUser(messages, this.userId),\n\t\t\t\toffset,\n\t\t\t\tcount,\n\t\t\t\ttotal,\n\t\t\t});\n\t\t},\n\t},","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/2a7de457074cbb4d4373fbd9a4e5bea292c9c764/apps/meteor/server/api/v1/omnichannel/visitors.ts#L164-L200","documentation":"Thrown by GET /api/v1/livechat/:rid/messages when the room exists but canAccessRoomAsync(room, this.user) returns false. The caller passed the route-level view-l-room permission, but per-room access was denied: for a livechat room that typically means the caller is not the serving agent of that conversation and holds no overriding global livechat access. The check is per room, not per workspace.","triggerScenarios":"GET /api/v1/livechat/<rid>/messages as an authenticated user with view-l-room who is not the agent assigned to that chat (e.g. another department's agent), or as a user with no livechat role at all poking at a rid they found elsewhere.","commonSituations":"Agent A opens a conversation owned by agent B without takeover; scripts running with a bot/admin token that lacks livechat manager-style room access; department routing changed and the rid list in your tool is stale.","solutions":["Query rooms the caller can actually access: GET /api/v1/livechat/rooms returns only the agent's own conversations — drive UIs from that","If an agent needs another agent's room, transfer/take the chat via the omnichannel endpoints first","Run service accounts with an appropriate livechat manager role if they must read arbitrary rooms"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch 'not-allowed' from livechat/:rid/messages and render an access-denied state; do not retry — request room transfer (omnichannel takeover endpoints) or use a service account with legitimate livechat access.","preventionTips":["Drive agent UIs from GET livechat/rooms, which only returns rooms the agent can access","Run integration scripts with an account holding a livechat manager role","After department re-routing, refresh cached rid lists before fetching messages"],"tags":["omnichannel","livechat","permissions","authorization","rest-api"],"backgroundTag":"permission-denied","analyzedSha":"2a7de457074cbb4d4373fbd9a4e5bea292c9c764","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}