RocketChat/Rocket.Chat · error · MeteorError
error-max-guests-number-reached
error-max-guests-number-reached
Error message
Maximum number of guests reached.
What it means
Thrown by validateUserRoles when a user is being changed into a guest (roles === ['guest'] where they were not previously a guest) and License.shouldPreventAction('guestUsers') is true — i.e. the enterprise license's guest-user quota is exhausted. MeteorError code 'error-max-guests-number-reached', method 'insertOrUpdateUser', field 'Assign_role'. Apps and bots (isSpecialType) short-circuit before this check.
Source
Thrown at apps/meteor/ee/server/lib/authorization/validateUserRoles.ts:26
const isApp = Boolean(userData.type === 'app');
const wasApp = Boolean(currentUserData?.type === 'app');
const isBot = Boolean(userData.type === 'bot');
const wasBot = Boolean(currentUserData?.type === 'bot');
const isGuest = Boolean(userData.roles?.includes('guest') && userData.roles.length === 1);
const wasGuest = Boolean(currentUserData?.roles?.includes('guest') && currentUserData.roles.length === 1);
const isSpecialType = isApp || isBot;
const hasGuestToChanged = isGuest && !wasGuest;
if (isSpecialType) {
return;
}
if (hasGuestToChanged && (await License.shouldPreventAction('guestUsers'))) {
throw new MeteorError('error-max-guests-number-reached', 'Maximum number of guests reached.', {
method: 'insertOrUpdateUser',
field: 'Assign_role',
});
}
if (isGuest) {
return;
}
const isActive = Boolean(userData.active !== false);
const wasActive = currentUserData && currentUserData?.active !== false;
const hasRemovedSpecialType = (wasApp && !isApp) || (wasBot && !isBot);
if (!isActive) {
return;
}
View on GitHub (pinned to f9d3ec372b)
Solutions
- Free up a guest seat by converting an existing guest to a regular user or deactivating them, then retry.
- Upgrade the license to raise the guestUsers cap.
- If the conversion is not required, keep the user as a regular user instead of demoting to guest.
- Before bulk operations, check current guest count against the license limit.
Example fix
// before: demote beyond limit
await Users.updateOne({ _id }, { $set: { roles: ['guest'] } });
await validateUserRoles({ roles: ['guest'] }, currentUserData);
// after: verify headroom first
if (await License.shouldPreventAction('guestUsers')) {
throw new Error('Convert an existing guest first or upgrade the license');
} Defensive patterns
Strategy: validation
Validate before calling
async function canDemoteToGuest(): Promise<boolean> {
return !(await License.shouldPreventAction('guestUsers'));
} Type guard
const isGuestOnly = (roles: unknown): roles is ['guest'] => Array.isArray(roles) && roles.length === 1 && roles[0] === 'guest';
Try / catch
try { await validateUserRoles({ roles: ['guest'] }, current); } catch (e) {
if (e?.error === 'error-max-guests-number-reached') { /* free a seat or upgrade */ } else throw e;
} Prevention
- Check the guest-seat headroom before bulk guest conversions.
- Track license caps in admin dashboards so operators see remaining seats.
When it happens
Trigger: Admin assigns the 'guest' role to a previously non-guest user (demoting them) when the guest quota is full; bulk user import that converts users to guests beyond the limit; UI 'Assign_role' action that flips a user to guest-only.
Common situations: License downgrade reduced the guest allowance; trial license guest seats exhausted; org converted many users to guests for a partner rollout.
Related errors
- error-action-not-allowed
- error-license-user-limit-reached
- error-license-user-limit-reached
- error-max-rooms-per-guest-reached
- error-action-not-allowed
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/e5ba5a998362a50c.
Report an issue: GitHub.