{"record":{"id":"41f8b0e563394b40","repo":"RocketChat/Rocket.Chat","slug":"error-not-allowed-41f8b0","errorCode":null,"errorMessage":"error-not-allowed","messagePattern":"error-not-allowed","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/lib/visitors.ts","lineNumber":62,"sourceCode":"}\n\nexport async function findChatHistory({\n\tuserId,\n\troomId,\n\tvisitorId,\n\tpagination: { offset, count, sort },\n}: {\n\tuserId: IUser['_id'];\n\troomId: IRoom['_id'];\n\tvisitorId: IVisitor['_id'];\n\tpagination: { offset: number; count: number; sort: FindOptions<IOmnichannelRoom>['sort'] };\n}) {\n\tconst room = await LivechatRooms.findOneById(roomId);\n\tif (!room) {\n\t\tthrow new Error('invalid-room');\n\t}\n\tif (!(await canAccessRoomAsync(room, { _id: userId }))) {\n\t\tthrow new Error('error-not-allowed');\n\t}\n\n\tconst extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {}, { userId });\n\tconst { cursor, totalCount } = LivechatRooms.findPaginatedByVisitorId(\n\t\tvisitorId,\n\t\t{\n\t\t\tsort: sort || { ts: -1 },\n\t\t\tskip: offset,\n\t\t\tlimit: count,\n\t\t},\n\t\textraQuery,\n\t);\n\n\tconst [history, total] = await Promise.all([cursor.toArray(), totalCount]);\n\n\treturn {\n\t\thistory,\n\t\tcount: history.length,","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/v1/omnichannel/lib/visitors.ts#L44-L80","documentation":"After the room resolves, findChatHistory (GET /api/v1/livechat/visitors.chathistory/:roomId/:visitorId) checks canAccessRoomAsync(room, { _id: userId }); when the requesting user cannot access that omnichannel room it throws 'error-not-allowed'. Access typically requires being the serving agent, a room member, or holding broad omnichannel read permissions.","triggerScenarios":"An agent without membership in the room (not servedBy, not a member) requests another agent's chat history; a plain authenticated user with no view-l-room/omnichannel-manager permissions calls the endpoint.","commonSituations":"Agents opening arbitrary visitor histories from a shared list without being assigned; custom roles missing omnichannel permissions; supervisors without the livechat-manager/monitor role trying to read all conversations.","solutions":["Ensure the caller is the room's serving agent or a member; otherwise assign the room first.","Grant view-l-room to the role, or use livechat-manager / omnichannel monitor roles for supervisors who must read all chats.","Scope your UI so agents only request histories of rooms they can access."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Only fetch history for rooms the caller can access\nconst accessible = await canAccessRoom(roomId, userId); // rooms.info membership check or room list lookup\nif (!accessible) throw new ForbiddenError('caller cannot access this room');\nreturn getChatHistory({ userId, roomId, visitorId, pagination });","typeGuard":null,"tryCatchPattern":"try { return await getChatHistory({ userId, roomId, visitorId, pagination }); } catch (e) { if (e.message === 'error-not-allowed') return forbiddenPage(); throw e; }","preventionTips":["Scope history UI to rooms the agent serves or monitors.","Grant view-l-room or livechat-manager/monitor to supervisors who need cross-room reads.","Don't run chat-history scripts with service credentials that have no room membership."],"tags":["omnichannel","chat-history","authorization","room-access","rest-api"],"backgroundTag":"permission-denied","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}