RocketChat/Rocket.Chat · error · MeteorError
error-mac-limit-reached
error-mac-limit-reached
Error message
error-mac-limit-reached
What it means
BeforeSaveCheckMAC is a message pre-save hook enforcing the 'monthly active contacts' (MAC) enterprise license limit on omnichannel rooms. Omnichannel.isWithinMACLimit(room) returns true if the visitor already has activity recorded for the current UTC month; otherwise it checks whether the license still allows the 'monthlyActiveContacts' action. When a new contact's message would exceed the licensed MAC quota, the hook throws Meteor error-mac-limit-reached and the message is not saved. Bot messages (message.token) and system messages (message.t) are exempt.
Source
Thrown at apps/meteor/server/services/messages/hooks/BeforeSaveCheckMAC.ts:21
import type { IRoom, IMessage } from '@rocket.chat/core-typings';
export class BeforeSaveCheckMAC {
async isWithinLimits({ message, room }: { message: IMessage; room: IRoom }): Promise<void> {
if (!isOmnichannelRoom(room)) {
return;
}
if (message.token) {
return;
}
if (message.t) {
return;
}
const canSendMessage = await Omnichannel.isWithinMACLimit(room);
if (!canSendMessage) {
throw new MeteorError('error-mac-limit-reached');
}
}
}
View on GitHub (pinned to b2c16d5842)
Solutions
- Raise the monthlyActiveContacts limit on the license (upgrade/renew) so new contacts are allowed again
- Wait for the UTC month to roll over — MAC counting resets monthly
- Verify license validity: an absent or invalidated license falls back to CE behavior with no MAC limit, so a wrongly flagged limit can indicate a license validation issue
- Short-term, prioritize ongoing conversations whose contacts are already active this month
Defensive patterns
Strategy: validation
Validate before calling
import { Omnichannel } from '@rocket.chat/core-services';
const withinLimit = await Omnichannel.isWithinMACLimit(room);
if (!withinLimit) {
// do not call sendMessage for this room; surface a license-limit notice instead
throw new LicenseLimitError('monthlyActiveContacts');
} Try / catch
try {
await sendMessage(userId, { rid, msg });
} catch (err) {
if (err?.error === 'error-mac-limit-reached' || err?.reason === 'error-mac-limit-reached') {
// NOT retryable: quota/licensing must change (limit raise, license fix, or month rollover)
return notifyLicenseLimitReached();
}
throw err;
} Prevention
- Monitor monthlyActiveContacts usage against the licensed limit before it is reached
- Treat error-mac-limit-reached as non-retryable — the quota, not the network, is the cause
- Remember the check is per visitor and per UTC month; already-active contacts never re-trigger it
- An invalid/absent license removes the limit (CE behavior), so also verify license validity when the error is unexpected
When it happens
Trigger: Sending a message in an omnichannel room whose visitor has no activity entry for the current month (moment.utc().format('YYYY-MM')) while the workspace has reached its monthlyActiveContacts license limit — the counter quota is exhausted for the month.
Common situations: Enterprise license MAC cap hit mid-month as new contacts write in; quota shrunk after renewal/downgrade; the omnichannel queue worker also stops on limit reached (License.onLimitReached), so new inquiries stall alongside this error.
Related errors
- error-max-departments-number-reached
- error-action-not-allowed
- error-action-not-allowed
- Cloud connectivity is disabled by the offline license applie
- error-invalid-contact
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/e98d9daa30a5a140.
Report an issue: GitHub.