RocketChat/Rocket.Chat · error · MeteorError
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
MeteorError('error-invalid-user', 'Invalid user') thrown by removeUserFromRolesAsync when the userId has no matching user document. The existence check runs before role validation, so a bad user id fails even if the roles are valid.
Source
Thrown at apps/meteor/server/lib/roles/removeUserFromRoles.ts:16
import { MeteorError } from '@rocket.chat/core-services';
import type { IRole, IUser, IRoom } from '@rocket.chat/core-typings';
import { Users, Subscriptions, Roles } from '@rocket.chat/models';
import { syncRoomRolePriorityForUserAndRoom } from './syncRoomRolePriority';
import { validateRoleList } from './validateRoleList';
import { notifyOnSubscriptionChangedByRoomIdAndUserId } from '../notifyListener';
export const removeUserFromRolesAsync = async (userId: IUser['_id'], roles: IRole['_id'][], scope?: IRoom['_id']): Promise<boolean> => {
if (!userId || !roles) {
return false;
}
const user = await Users.findOneById(userId, { projection: { _id: 1 } });
if (!user) {
throw new MeteorError('error-invalid-user', 'Invalid user');
}
if (!(await validateRoleList(roles))) {
throw new MeteorError('error-invalid-role', 'Invalid role');
}
if (process.env.NODE_ENV === 'development' && (scope === 'Users' || scope === 'Subscriptions')) {
throw new Error('Roles.removeUserRoles method received a role scope instead of a scope value.');
}
for await (const roleId of roles) {
const role = await Roles.findOneById<Pick<IRole, '_id' | 'scope'>>(roleId, { projection: { scope: 1 } });
if (!role) {
continue;
}
if (role.scope === 'Subscriptions' && scope) {
const removeRolesResponse = await Subscriptions.removeRolesByUserId(userId, [roleId], scope);View on GitHub (pinned to b2c16d5842)
Solutions
- Look the user up (Users.findOneById / users.info API) and drop or fix the work item.
- Treat removal for a deleted user as a skip, not a batch failure.
- Re-sync automation user lists to remove stale ids.
Example fix
// before
await removeUserFromRolesAsync(userId, ['bot']); // throws error-invalid-user
// after
const user = await Users.findOneById(userId, { projection: { _id: 1 } });
if (user) {
await removeUserFromRolesAsync(userId, ['bot']);
} Defensive patterns
Strategy: validation
Validate before calling
const user = await Users.findOneById(userId, { projection: { _id: 1 } });
if (!user) {
// nothing to de-role: skip instead of failing the batch
} else {
await removeUserFromRolesAsync(userId, roles, scope);
} Try / catch
try {
await removeUserFromRolesAsync(userId, roles, scope);
} catch (error: any) {
if (error?.error === 'error-invalid-user') {
// user deleted: drop the work item and continue
}
} Prevention
- Filter deleted users out of role-cleanup batches.
- Handle 'error-invalid-user' as a skip, not a batch failure.
- Re-sync automation user lists after deletions.
When it happens
Trigger: Removing roles from a user id that was deleted or never existed: stale job payloads, scripts, or retried API requests after user deletion.
Common situations: User deleted while a role-cleanup job was queued; imported data with dangling user references; retrying an old moderation action.
Related errors
- error-duplicate-role-names-not-allowed
- error-invalid-scope
- error-invalid-scope
- error-user-not-found
- error-user-param-not-provided
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/ab91284b3080b90d.
Report an issue: GitHub.