RocketChat/Rocket.Chat · error · Meteor.Error

error-action-not-allowed

error-action-not-allowed

Error message

Mailing is not allowed

What it means

Thrown by POST rooms.mail when the calling user lacks the 'mail-messages' permission for the given room (rid). The mail/export route is gated behind a permission usually reserved for admins/moderators; without it the request never proceeds.

Source

Thrown at apps/meteor/server/api/v1/rooms.ts:1012

		response: {
			200: ajv.compile<void | { missing: string[] }>({
				type: 'object',
				properties: {
					success: { type: 'boolean', enum: [true] },
					missing: { type: 'array', items: { type: 'string' } },
				},
				required: ['success'],
				additionalProperties: false,
			}),
			400: validateBadRequestErrorResponse,
			401: validateUnauthorizedErrorResponse,
		},
	},
	async function action() {
		const { rid, type } = this.bodyParams;

		if (!(await hasPermissionAsync(this.user, 'mail-messages', rid))) {
			throw new Meteor.Error('error-action-not-allowed', 'Mailing is not allowed');
		}

		const room = await Rooms.findOneById(rid);
		if (!room) {
			throw new Meteor.Error('error-invalid-room');
		}

		const user = await Users.findOneById(this.userId);

		if (!user || !(await canAccessRoomAsync(room, user))) {
			throw new Meteor.Error('error-not-allowed', 'Not Allowed');
		}

		if (type === 'file') {
			const { dateFrom, dateTo } = this.bodyParams;
			const { format } = this.bodyParams;

			const convertedDateFrom = dateFrom ? new Date(dateFrom) : new Date(0);

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Grant 'mail-messages' to the user's role in Permissions admin (or via permissions API).
  2. If the feature shouldn't be exposed, hide the UI control for users without the permission.
  3. For scoped setups, ensure the permission is granted for the specific rid/channel, not just globally.

Example fix

// before
await rest.post('/api/v1/rooms.mail', { rid, type: 'email' });

// after
const me = await rest.get('/api/v1/me');
if (!me.permissions?.includes('mail-messages')) {
  notifyUser('Mailing requires the mail-messages permission.');
} else {
  await rest.post('/api/v1/rooms.mail', { rid, type: 'email' });
}
Defensive patterns

Strategy: validation

Validate before calling

const me = await rest.get('/api/v1/me');
const canMail = (me.roles ?? []).some(r => ['admin'].includes(r))
  || (me.permissions ?? []).includes('mail-messages');
if (!canMail) throw new Error('mail-messages permission required');

Type guard

function hasMailPermission(perms: string[] | undefined): boolean {
  return Array.isArray(perms) && perms.includes('mail-messages');
}

Try / catch

try {
  await rest.post('/api/v1/rooms.mail', { rid, type });
} catch (e) {
  if (isMeteorError(e, 'error-action-not-allowed')) {
    notify('You need the mail-messages permission.');
  } else throw e;
}

Prevention

When it happens

Trigger: POST /api/v1/rooms.mail with { rid, type } where hasPermissionAsync(user, 'mail-messages', rid) is false.

Common situations: Regular (non-admin) users trying the mail/export feature; permission renamed or removed in a policy reset; custom role that forgot to include 'mail-messages'; scoped permissions not granted for the target room.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/03027699c184d076. Report an issue: GitHub.