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

  1. Raise the monthlyActiveContacts limit on the license (upgrade/renew) so new contacts are allowed again
  2. Wait for the UTC month to roll over — MAC counting resets monthly
  3. 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
  4. 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

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


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/e98d9daa30a5a140. Report an issue: GitHub.