RocketChat/Rocket.Chat · error · MeteorError
error-invalid-roleId
error-invalid-roleId
Error message
This role does not exist
What it means
Thrown by updateRole in updateRole.ts:20 when Roles.findOneById(roleId) returns null — the role being edited does not exist. MeteorError code 'error-invalid-roleId'.
Source
Thrown at apps/meteor/ee/server/lib/roles/updateRole.ts:20
import type { IRole } from '@rocket.chat/core-typings';
import { Roles } from '@rocket.chat/models';
import { isValidRoleScope } from '../../../../lib/roles/isValidRoleScope';
import { notifyOnRoleChangedById } from '../../../../server/lib/notifyListener';
type UpdateRoleOptions = {
broadcastUpdate?: boolean;
};
export const updateRole = async (
roleId: IRole['_id'],
roleData: Omit<IRole, '_id' | '_updatedAt'>,
options: UpdateRoleOptions = {},
): Promise<IRole> => {
const role = await Roles.findOneById(roleId);
if (!role) {
throw new MeteorError('error-invalid-roleId', 'This role does not exist');
}
if (role.protected && ((roleData.name && roleData.name !== role.name) || (roleData.scope && roleData.scope !== role.scope))) {
throw new MeteorError('error-role-protected', 'Role is protected');
}
if (roleData.name) {
const otherRole = await Roles.findOneByName(roleData.name, { projection: { _id: 1 } });
if (otherRole && otherRole._id !== role._id) {
throw new MeteorError('error-duplicate-role-names-not-allowed', 'Role name already exists');
}
} else {
roleData.name = role.name;
}
if (roleData.scope) {
if (!isValidRoleScope(roleData.scope)) {
throw new MeteorError('error-invalid-scope', 'Invalid scope');View on GitHub (pinned to f9d3ec372b)
Solutions
- Refresh the role list and confirm the _id before editing.
- Catch MeteorError 'error-invalid-roleId' and surface 'role no longer exists'.
- Treat as idempotent no-op if the user's intent was deletion.
Example fix
// before
await updateRole(roleId, roleData);
// after
if (!(await Roles.findOneById(roleId))) {
throw new Error('role vanished; refresh');
}
await updateRole(roleId, roleData); Defensive patterns
Strategy: validation
Validate before calling
if (!(await Roles.findOneById(roleId))) throw new Error('role vanished'); Type guard
const roleExists = async (id: string) => Boolean(await Roles.findOneById(id, { projection: { _id: 1 } })); Try / catch
try { await updateRole(roleId, roleData); }
catch (e) {
if (e?.code === 'error-invalid-roleId') { /* refresh list */ return; }
throw e;
} Prevention
- Refetch the role before opening the edit form.
- Avoid caching role ids in long-lived UI.
When it happens
Trigger: Calling updateRole with a roleId that was deleted, never existed, or is malformed. Concurrent deletion between load and save.
Common situations: Stale role-management UI; double-submit after the first call deleted-then-updated; CI using an outdated role id fixture.
Related errors
- error-duplicate-role-names-not-allowed
- error-invalid-scope
- error-role-protected
- error-duplicate-role-names-not-allowed
- error-invalid-scope
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/df3fa74c74070445.
Report an issue: GitHub.