RocketChat/Rocket.Chat · error · MeteorError
error-invalid-scope
error-invalid-scope
Error message
Invalid scope
What it means
The same isValidRoleScope gate on the update path: when roleData.scope is provided it must be exactly 'Users' or 'Subscriptions', otherwise updateRole throws MeteorError('error-invalid-scope', 'Invalid scope'). Omitting the field is safe - it is backfilled from the existing role (roleData.scope = role.scope) - so the error only fires on an explicitly supplied invalid value.
Solutions
- Send exactly 'Users' or 'Subscriptions', or omit scope entirely to keep the current value.
- Validate the enum in the API schema (ajv) before the payload reaches updateRole.
- Trim and canonicalize the scope string client-side before submitting.
Example fix
// before
await updateRole(roleId, { scope: 'global' }); // throws error-invalid-scope
// after
await updateRole(roleId, { scope: 'Subscriptions' }); // or omit scope to keep current value Defensive patterns
Strategy: validation
Validate before calling
if (roleData.scope !== undefined && roleData.scope !== 'Users' && roleData.scope !== 'Subscriptions') {
// invalid scope; fix the payload or omit the field to keep the current value
} Type guard
type RoleScope = 'Users' | 'Subscriptions'; const isRoleScope = (scope: unknown): scope is RoleScope => scope === 'Users' || scope === 'Subscriptions';
Try / catch
try {
await updateRole(roleId, roleData);
} catch (e: any) {
if (e?.error === 'error-invalid-scope') throw new Meteor.Error(400, "scope must be 'Users' or 'Subscriptions'");
throw e;
} Prevention
- Use a dropdown limited to 'Users' and 'Subscriptions' instead of free-text scope inputs.
- Omit scope from partial-update payloads when it is not being changed.
- Validate the enum client-side and at the API schema before server code runs.
When it happens
Trigger: A role update payload carrying scope 'global', 'users' (case mismatch), 'Subscriptions ' (trailing space), or any free-text value instead of the two allowed literals.
Common situations: Same causes as the insert variant: hand-built payloads, legacy scope vocabulary from imports, enum not enforced on the client, or form fields that let users type arbitrary scope strings.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- error-invalid-scope
- error-action-not-allowed
- error-duplicate-role-names-not-allowed
- error-duplicate-role-names-not-allowed
- error-invalid-contact-manager
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/175a76e5b4d30936.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/ee/server/lib/roles/updateRole.ts:38
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');
}
} 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);View on GitHub (pinned to b2c16d5842)