RocketChat/Rocket.Chat · error · Error

error-not-allowed

error-not-allowed

Error message

error-not-allowed

What it means

Thrown by GET livechat/room.join when canAccessRoomAsync(room, user) returns false. Even with view-l-room permission, the user must pass the room-level access check; for Livechat rooms this typically requires being the assigned agent, a manager/admin, or a member of the department. The guard enforces per-room authorization after the global permission gate.

Source

Thrown at apps/meteor/server/api/v1/omnichannel/room.ts:430

				throw new Error('error-invalid-user');
			}

			const room = await LivechatRooms.findOneById(roomId);

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

			if (!room.open) {
				throw new Error('room-closed');
			}

			if (!(await Omnichannel.isWithinMACLimit(room))) {
				throw new Error('error-mac-limit-reached');
			}

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

			await addUserToRoom(roomId, user);

			return API.v1.success();
		},
	},
);

API.v1.addRoute(
	'livechat/room.saveInfo',
	{ authRequired: true, permissionsRequired: ['view-l-room'], validateParams: isLiveChatRoomSaveInfoProps },
	{
		async post() {
			const { roomData, guestData } = this.bodyParams;
			const room = await LivechatRooms.findOneById(roomData._id);
			if (!room || !isOmnichannelRoom(room)) {
				throw new Error('error-invalid-room');

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Grant the user membership in the room's department or assign them as a co-agent.
  2. Give the user view-livechat-manager (or equivalent) for cross-department monitoring.
  3. Confirm the user still holds view-l-room; permission revocation is a common cause.
  4. Use the proper supervisor/monitor role instead of forcing a direct join.

Example fix

// before
await GET('/api/v1/livechat/room.join', { roomId });

// after
if (!await canAccessRoomAsync(room, user)) {
  await requestDepartmentMembership(room.departmentId, user._id);
  return;
}
await GET('/api/v1/livechat/room.join', { roomId });
Defensive patterns

Strategy: validation

Validate before calling

const allowed = await canAccessRoomAsync(room, user);
if (!allowed) throw new ClientError('not-allowed');

Type guard

null

Try / catch

try {
  await GET('/api/v1/livechat/room.join', { roomId });
} catch (e) {
  if (e.message === 'error-not-allowed') { requestDepartmentAccess(room.departmentId); return; }
  throw e;
}

Prevention

When it happens

Trigger: GET livechat/room.join?roomId=... by an agent who is not the serving agent, not in the room's department, and lacks manager-level omnichannel permissions. Also when a non-omnichannel user with view-l-room tries to join a department-restricted room.

Common situations: Agent from department A tries to join a department B room without cross-department permission; ex-serving agent whose assignment was revoked tries to rejoin; user has view-l-room but not view-livechat-manager or livechat-monitoring.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/bf9c5997d81c3f4b. Report an issue: GitHub.