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 (wired into user create/update and role assignment flows as method 'insertOrUpdateUser') when a user is becoming a guest (roles exactly ['guest'] and previously not) and the license's guest-user allowance is exhausted (License.shouldPreventAction('guestUsers')). App and bot user types bypass the check. It enforces the enterprise guest-seat limit at the moment the guest role is granted.
Solutions
- Convert other guests back to regular users (or deactivate them) to free guest seats, then retry
- Apply a license with a higher guestUsers allowance (Administration > License)
- For imports, throttle guest role assignment until the license is upgraded
Example fix
// before: assigning the guest role and letting the hook throw
await insertOrUpdateUser({ ...userData, roles: ['guest'] });
// after: pre-check the same license gate
import { License } from '@rocket.chat/license';
const becomingGuest = (userData.roles ?? []).includes('guest') && (currentUserData?.roles ?? []).join() !== 'guest';
if (becomingGuest && (await License.shouldPreventAction('guestUsers'))) {
throw new Error('Guest seat limit reached; upgrade the license first');
}
await insertOrUpdateUser({ ...userData, roles: ['guest'] }); Defensive patterns
Strategy: validation
Validate before calling
import { License } from '@rocket.chat/license';
const canAddGuest = async (): Promise<boolean> => !(await License.shouldPreventAction('guestUsers')); Type guard
const isGuestOnlyRoles = (roles?: string[]): boolean =>
Boolean(roles?.includes('guest') && roles.length === 1); Try / catch
try {
await insertOrUpdateUser({ ...userData, roles: ['guest'] });
} catch (err: any) {
if (err?.error === 'error-max-guests-number-reached') {
// free a guest seat or upgrade the license before retrying the role assignment
}
throw err;
} Prevention
- Track guest-seat usage against the license before external-collaboration drives
- Remember app/bot users bypass the guest check entirely
- When converting users, only role changes toward guest-only trigger the gate
When it happens
Trigger: Creating a user with only the guest role, or editing an existing user's roles down to just 'guest', past the licensed guestUsers limit; SSO/LDAP provisioning assigning the guest role to new external users.
Common situations: External-collaboration onboarding exceeding purchased guest seats; guest role bulk-assigned during imports; license tier with few guest seats.
Related errors
- error-action-not-allowed
- error-license-user-limit-reached
- error-action-not-allowed
- error-action-not-allowed
- error-action-not-allowed
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/e5ba5a998362a50c.
Report an issue: GitHub.
Appendix: 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 b2c16d5842)