RocketChat/Rocket.Chat · error · Error

error-user-not-found

Error message

error-user-not-found

What it means

Thrown by syncUserRoles in syncUserRoles.ts:63 when the target user (uid) cannot be found by findOneById. The function rewrites a user's role set, so a missing user is a hard precondition failure. NOTE: plain `new Error('error-user-not-found')` — code is in the message, not structured.

Source

Thrown at apps/meteor/ee/server/lib/syncUserRoles.ts:63

		void api.broadcast('user.roleUpdate', {
			type,
			_id: roleId,
			u: {
				_id,
				username,
			},
		});
	}
}

export async function syncUserRoles(
	uid: IUser['_id'],
	newRoleList: Array<IRole['_id']>,
	{ allowedRoles, skipRemovingRoles, scope }: setUserRolesOptions,
): Promise<void> {
	const user = await Users.findOneById<Pick<IUser, '_id' | 'username' | 'roles'>>(uid, { projection: { username: 1, roles: 1 } });
	if (!user) {
		throw new Error('error-user-not-found');
	}

	const existingRoles = user.roles;
	const rolesToAdd = filterRoleList(newRoleList, existingRoles, allowedRoles);
	const rolesToRemove = filterRoleList(existingRoles, newRoleList, allowedRoles);

	if (!rolesToAdd.length && !rolesToRemove.length) {
		return;
	}

	const wasGuest = existingRoles.length === 1 && existingRoles[0] === 'guest';
	if (wasGuest && (await License.shouldPreventAction('activeUsers'))) {
		throw new Error('error-license-user-limit-reached');
	}

	if (rolesToAdd.length && (await addUserRolesAsync(uid, rolesToAdd, scope))) {
		broadcastRoleChange('added', rolesToAdd, user);
	}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Verify the user exists (Users.findOneById(uid)) before invoking syncUserRoles.
  2. Match by message 'error-user-not-found' in the catch and refresh the user list.
  3. Treat as no-op for archived/deleted users.

Example fix

// before
await syncUserRoles(uid, newRoles, opts);

// after
if (!(await Users.findOneById(uid, { projection: { _id: 1 } }))) {
  throw new Error('user missing; refresh');
}
await syncUserRoles(uid, newRoles, opts);
Defensive patterns

Strategy: validation

Validate before calling

if (!(await Users.findOneById(uid, { projection: { _id: 1 } }))) throw new Error('user missing');

Type guard

const userExists = async (uid: string) => Boolean(await Users.findOneById(uid, { projection: { _id: 1 } }));

Try / catch

try { await syncUserRoles(uid, newRoles, opts); }
catch (e) {
  if (e instanceof Error && e.message === 'error-user-not-found') { /* refresh user */ return; }
  throw e;
}

Prevention

When it happens

Trigger: Calling syncUserRoles with a uid that was deleted, never existed, or whose projection returned null. Often reached indirectly via role-assignment REST endpoints or user-edit flows.

Common situations: Client holds a stale uid; user was deleted between page load and role save; import job referencing archived user ids.

Related errors


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