RocketChat/Rocket.Chat · error · Error

not-allowed

not-allowed

Error message

not-allowed

What it means

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.

Solutions

  1. Query rooms the caller can actually access: GET /api/v1/livechat/rooms returns only the agent's own conversations — drive UIs from that
  2. If an agent needs another agent's room, transfer/take the chat via the omnichannel endpoints first
  3. Run service accounts with an appropriate livechat manager role if they must read arbitrary rooms
Defensive patterns

Strategy: try-catch

Try / catch

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.

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@2a7de45707 (2026-08-18). Data as JSON: /api/errors/a507c984be965c72. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/server/api/v1/omnichannel/visitors.ts:182

);

API.v1.addRoute(
	'livechat/:rid/messages',
	{ authRequired: true, permissionsRequired: ['view-l-room'], validateParams: isLivechatRidMessagesProps },
	{
		async get() {
			const { offset, count } = await getPaginationItems(this.queryParams);
			const { sort } = await this.parseJsonQuery();
			const { searchTerm } = this.queryParams;

			const room = await LivechatRooms.findOneById(this.urlParams.rid);

			if (!room) {
				throw new Error('invalid-room');
			}

			if (!(await canAccessRoomAsync(room, this.user))) {
				throw new Error('not-allowed');
			}

			const { cursor, totalCount } = Messages.findLivechatClosedMessages(this.urlParams.rid, searchTerm, {
				sort: sort || { ts: -1 },
				skip: offset,
				limit: count,
			});

			const [messages, total] = await Promise.all([cursor.toArray(), totalCount]);

			return API.v1.success({
				messages: await normalizeMessagesForUser(messages, this.userId),
				offset,
				count,
				total,
			});
		},
	},

View on GitHub (pinned to 2a7de45707)