RocketChat/Rocket.Chat · error · Error

invalid-user

Error message

invalid-user

What it means

Thrown by findMonitorByUsername when no user matches the username AND the 'livechat-monitor' role. The lookup requires both conditions: a user with that exact username who also holds the livechat-monitor role. Plain Error, code 'invalid-user' (note: no 'error-' prefix, unlike most codes in this area).

Source

Thrown at apps/meteor/ee/server/api/v1/omnichannel/lib/monitors.ts:67

}

export async function findMonitorByUsername({ username }: { username: string }): Promise<IUser> {
	const user = await Users.findOne(
		{ username, roles: 'livechat-monitor' },
		{
			projection: {
				username: 1,
				name: 1,
				status: 1,
				statusLivechat: 1,
				emails: 1,
				livechat: 1,
			},
		},
	);

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

	return user;
}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Confirm the user exists and holds the 'livechat-monitor' role via Users.findOne before calling.
  2. Match the username casing exactly (consider lowercasing both sides if usernames are case-insensitive elsewhere).
  3. Re-grant the livechat-monitor role if it was removed inadvertently.
  4. Handle the not-found case in the caller rather than propagating the raw error.

Example fix

// before: assume monitor exists
const monitor = await findMonitorByUsername({ username });

// after: validate role membership first
const candidate = await Users.findOne({ username }, { projection: { roles: 1, username: 1 } });
if (!candidate || !candidate.roles?.includes('livechat-monitor')) {
  throw new NotFoundError('livechat-monitor');
}
const monitor = await findMonitorByUsername({ username });
Defensive patterns

Strategy: validation

Validate before calling

// Validate the monitor exists with the role before lookup
import { Users } from '@rocket.chat/models';
const candidate = await Users.findOne({ username }, { projection: { roles: 1, username: 1 } });
if (!candidate || !candidate.roles?.includes('livechat-monitor')) {
  throw new NotFoundError('livechat-monitor');
}
await findMonitorByUsername({ username });

Type guard

function isLivechatMonitor(u: { roles?: string[] } | null | undefined): u is { roles: string[] } {
  return Array.isArray(u?.roles) && u.roles.includes('livechat-monitor');
}

Try / catch

try {
  return await findMonitorByUsername({ username });
} catch (e) {
  if (e.message === 'invalid-user') {
    return null; // caller treats null as not-found
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling findMonitorByUsername with a username that does not exist, or exists but is not a livechat-monitor; username case mismatch (Mongo exact match); monitor was deactivated/role removed.

Common situations: Monitor demoted/removed from the livechat-monitor role but still referenced; case-sensitivity in username lookup; typo in the username; monitor deleted.

Related errors


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