RocketChat/Rocket.Chat · error

error-invalid-agent

error-invalid-agent

Error message

error-invalid-agent

What it means

forwardRoomToAgent requires transferData.userId (the target agent); a falsy value throws error-invalid-agent before any database lookup. This is a required-argument guard, not a lookup failure - an existing-but-offline agent produces error-user-is-offline instead.

Source

Thrown at apps/meteor/server/lib/omnichannel/Helper.ts:497

			mentionIds: [],
		});
	}
};

export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: TransferData) => {
	if (!room?.open) {
		return false;
	}

	logger.debug({
		msg: 'Forwarding room to agent',
		roomId: room._id,
		userId: transferData.userId,
	});

	const { userId: agentId, clientAction } = transferData;
	if (!agentId) {
		throw new Error('error-invalid-agent');
	}
	const user = await Users.findOneOnlineAgentById(
		agentId,
		settings.get<boolean>('Livechat_enabled_when_agent_idle'),
		settings.get<boolean>('Livechat_accept_chats_with_no_agents'),
		{},
	);
	if (!user) {
		logger.debug({
			msg: 'Agent is offline. Cannot forward',
			agentId,
		});
		throw new Error('error-user-is-offline');
	}

	const { _id: rid, servedBy: oldServedBy } = room;
	const inquiry = await LivechatInquiry.findOneByRoomId(rid, {});
	if (!inquiry) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Include a non-empty userId in transferData when forwarding to a specific agent
  2. If forwarding to a department only, use the department path that does not require userId
  3. Validate the payload shape at the API boundary before invoking the transfer

Example fix

// before
await forwardRoomToAgent(room, { clientAction: 'forward' }, guest);

// after
const { userId } = transferData;
if (!userId) throw new Error('error-invalid-agent');
await forwardRoomToAgent(room, { ...transferData, userId }, guest);
Defensive patterns

Strategy: validation

Validate before calling

const isNonEmptyId = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;
if (!isNonEmptyId(transferData.userId)) {
  throw new Error('error-invalid-agent');
}
await forwardRoomToAgent(room, transferData, guest);

Type guard

const isNonEmptyId = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;

Try / catch

try {
  await forwardRoomToAgent(room, transferData, guest);
} catch (err) {
  if (err instanceof Error && err.message === 'error-invalid-agent') {
    // payload lost userId - rebuild transferData and resubmit
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the livechat transfer/forward flow (e.g. livechat/room.forward REST endpoint) without userId in the payload; building transferData from a form where the agent select was cleared; field-name mismatch such as user_id vs userId.

Common situations: Frontend sends only { roomId, departmentId } but routes into the agent-forward branch; integrations that assume the agent is optional; agent picker cleared before submit.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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