RocketChat/Rocket.Chat · error · Error

Invalid agentId

Error message

Invalid agentId

What it means

Thrown by AppLivechatBridge.findOpenRoomsByAgentId when the supplied agentId is falsy. The bridge refuses to query LivechatRooms.findOpenByAgent with an empty id because it would either return nothing meaningful or match unintended documents. This is a guard against undefined/null leaking from App code.

Source

Thrown at apps/meteor/app/apps/server/bridges/livechat.ts:164

		const visitor = this.orch.getConverters()?.get('visitors').convertAppVisitor(room.visitor);

		const closeData: any = {
			room: await this.orch.getConverters()?.get('rooms').convertAppRoom(room),
			comment,
			...(user && { user }),
			...(visitor && { visitor }),
		};

		await closeRoom(closeData);

		return true;
	}

	protected async findOpenRoomsByAgentId(agentId: string, appId: string): Promise<ILivechatRoom[]> {
		this.orch.debugLog(`The App ${appId} is looking for livechat rooms associated with agent ${agentId}`);

		if (!agentId) {
			throw new Error('Invalid agentId');
		}

		const rooms = await LivechatRooms.findOpenByAgent(agentId).toArray();
		return Promise.all(rooms.map((room) => this.orch.getConverters()?.get('rooms').convertRoom(room) as Promise<ILivechatRoom>));
	}

	protected async countOpenRoomsByAgentId(agentId: string, appId: string): Promise<number> {
		this.orch.debugLog(`The App ${appId} is counting livechat rooms associated with agent ${agentId}`);

		if (!agentId) {
			throw new Error('Invalid agentId');
		}

		return LivechatRooms.countOpenByAgent(agentId);
	}

	protected async findRooms(visitor: IVisitor, departmentId: string | null, appId: string): Promise<Array<ILivechatRoom>> {
		this.orch.debugLog(`The App ${appId} is looking for livechat visitors.`);

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Ensure agentId is a non-empty string before calling the accessor (guard with an if or early return).
  2. Trace where agentId is sourced and confirm the producer always sets it.
  3. Add a runtime assertion / parameter validation in the App before invoking the read.
  4. Distinguish 'no agent' from 'empty agent' at the call site.

Example fix

// before
const rooms = await app.getLivechatRead().getOpenRooms(agent?.id);

// after
if (!agent?.id) {
  return [];
}
const rooms = await app.getLivechatRead().getOpenRooms(agent.id);
Defensive patterns

Strategy: validation

Validate before calling

function assertAgentId(agentId: string | undefined): asserts agentId is string {
  if (!agentId || typeof agentId !== 'string') {
    throw new Error('agentId is required to find open livechat rooms');
  }
}
assertAgentId(agentId);
await app.getLivechatRead().getOpenRooms(agentId);

Type guard

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

Try / catch

try {
  return await app.getLivechatRead().getOpenRooms(agentId);
} catch (e) {
  if ((e as Error).message === 'Invalid agentId') return [];
  throw e;
}

Prevention

When it happens

Trigger: An App calls the livechat read accessor to find open rooms for an agent (e.g. app.getLivechatRead().getOpenRooms(agentId)) with agentId being undefined, null, or empty string.

Common situations: App reads agentId from a context object that did not populate it; App iterates a list and passes an empty slot; App passes a visitor token or username where an agent user id is expected; refactoring dropped the agentId argument.

Related errors


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