RocketChat/Rocket.Chat · error · MeteorError

error-role-not-found

error-role-not-found

Error message

Role not found

What it means

After Roles.updateById succeeds and change notifications are broadcast, updateRole re-fetches the role; if findOneById now returns null it throws MeteorError('error-role-not-found', 'Role not found'). Because the role existed at the start of the function (checked at the top), this error signals the role was deleted concurrently between the initial lookup and the post-update re-fetch - a race, not a bad request.

Solutions

  1. Treat it as a conflict: re-check whether the role still exists; if it was intentionally deleted, the update is moot and can be dropped.
  2. If the update still matters, retry the whole operation against a role id that verifiably exists.
  3. Serialize role administration (single operator or tool at a time) so delete and update cannot interleave.

Example fix

// before
const updated = await updateRole(roleId, data); // throws error-role-not-found on a delete race

// after
try {
	const updated = await updateRole(roleId, data);
} catch (e: any) {
	if (e?.error === 'error-role-not-found' && !(await Roles.findOneById(roleId))) {
		return; // role deleted concurrently; nothing left to update
	}
	throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
	const updated = await updateRole(roleId, roleData);
} catch (e: any) {
	if (e?.error === 'error-role-not-found' && !(await Roles.findOneById(roleId))) {
		return; // deleted concurrently; the update is moot - reconcile and stop
	}
	throw e;
}

Prevention

When it happens

Trigger: Two admins (or admin UI plus an API script) operating on the same role: one calls updateRole while the other deletes the role mid-flight; the update path completes its write and side effects, then fails to re-read the now-deleted document.

Common situations: Role management screens left open in multiple tabs; cleanup automation that removes 'unused' roles racing with manual edits; retrying an update against an id that was deleted between attempts.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/03a7bbbb714449fd. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/ee/server/lib/roles/updateRole.ts:58

	} else {
		roleData.scope = role.scope;
	}

	await Roles.updateById(roleId, roleData.name, roleData.scope, roleData.description, roleData.mandatory2fa);

	void notifyOnRoleChangedById(roleId);

	if (options.broadcastUpdate) {
		void api.broadcast('user.roleUpdate', {
			type: 'changed',
			_id: roleId,
			scope: roleData.scope,
		});
	}

	const updatedRole = await Roles.findOneById(roleId);
	if (!updatedRole) {
		throw new MeteorError('error-role-not-found', 'Role not found');
	}

	return updatedRole;
};

View on GitHub (pinned to b2c16d5842)