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
- Confirm the user exists and holds the 'livechat-monitor' role via Users.findOne before calling.
- Match the username casing exactly (consider lowercasing both sides if usernames are case-insensitive elsewhere).
- Re-grant the livechat-monitor role if it was removed inadvertently.
- 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
- Match username casing exactly; normalize case if usernames are case-insensitive in your UI.
- Remove dangling monitor references when a user loses the livechat-monitor role.
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
- error-contact-not-found
- error-visitor-not-found
- error-invalid-inquiry
- error-invalid-sla
- error-invalid-provider
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/85fa242e0b60b17d.
Report an issue: GitHub.