RocketChat/Rocket.Chat · error · Error

error-invalid-visitor

Error message

error-invalid-visitor

What it means

Thrown by POST /api/v1/livechat/room.forward when LivechatVisitors.findOneEnabledById(room.v?._id) returns null — the room's visitor either does not exist or is disabled. findOneEnabledById filters on the visitor's enabled flag, so a deliberately disabled visitor fails even though the room references it.

Solutions

  1. Check the visitor: GET livechat/visitor.info (agent API) by token/_id; if disabled, re-enable the visitor or abandon the forward
  2. If the visitor was blocked in error, unblock and retry
  3. For orphaned rooms (visitor gone), close the room instead of forwarding it
Defensive patterns

Strategy: try-catch

Try / catch

try { await forward(roomId, payload); } catch (e) { if (e.message === 'error-invalid-visitor') { await closeOrphanedRoom(roomId); return; } throw e; }

Prevention

When it happens

Trigger: Forwarding a room whose visitor record was deleted, or whose visitor was disabled (blocked) after the conversation opened — e.g. an agent blocks the visitor mid-chat and a supervisor then attempts a forward.

Common situations: Visitor blocking/cleanup automations racing with transfers; test rooms created against visitors later wiped from the database; data imports that dropped visitors but kept rooms.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

				transferredTo?: { _id: string; username?: string; name?: string };
			};

			const room = await LivechatRooms.findOneById(this.bodyParams.roomId);
			if (room?.t !== 'l') {
				throw new Error('error-invalid-room');
			}

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

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

			const guest = await LivechatVisitors.findOneEnabledById(room.v?._id);
			if (!guest) {
				throw new Error('error-invalid-visitor');
			}

			transferData.transferredBy = normalizeTransferredByData(this.user, room);
			if (transferData.userId) {
				const userToTransfer = await Users.findOneById(transferData.userId);
				if (userToTransfer) {
					transferData.transferredTo = {
						_id: userToTransfer._id,
						username: userToTransfer.username,
						name: userToTransfer.name,
					};
				}
			}

			const chatForwardedResult = await transfer(room, guest, transferData);
			if (!chatForwardedResult) {
				throw new Error('error-forwarding-chat');
			}

View on GitHub (pinned to b2c16d5842)