RocketChat/Rocket.Chat · error · Meteor.Error

error-not-allowed

error-not-allowed

Error message

Threads Disabled

What it means

Thrown by the chat.readThread endpoint when the workspace setting Threads_enabled is false. The check fires before any input validation, so even a perfectly-formed request is rejected while threads are disabled. Meteor.Error code 'error-not-allowed'.

Source

Thrown at apps/meteor/server/api/v1/chat.ts:282

			response: {
				400: validateBadRequestErrorResponse,
				401: validateUnauthorizedErrorResponse,
				200: ajv.compile<void>({
					type: 'object',
					properties: {
						success: {
							type: 'boolean',
							enum: [true],
						},
					},
					required: ['success'],
					additionalProperties: false,
				}),
			},
		},
		async function action() {
			if (!settings.get<boolean>('Threads_enabled')) {
				throw new Meteor.Error('error-not-allowed', 'Threads Disabled');
			}

			const { tmid } = this.bodyParams;

			const thread = await Messages.findOneById(tmid, { projection: { rid: 1 } });
			if (!thread?.rid) {
				throw new Meteor.Error('error-invalid-message', 'Invalid Message');
			}

			const [user, room] = await Promise.all([
				Users.findOneById(this.userId),
				Rooms.findOneById(thread.rid, { projection: { ...roomAccessAttributes, t: 1, _id: 1 } }),
			]);

			if (!room) {
				throw new Meteor.Error('error-room-does-not-exist', 'This room does not exist');
			}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Enable Threads_enabled in Administration > Settings > Threads.
  2. Gate the client thread UI on a feature flag / settings query so readThread is never called when threads are off.
  3. Handle error-not-allowed with message 'Threads Disabled' gracefully (hide thread controls).

Example fix

// before
await fetch('/api/v1/chat.readThread', { method: 'POST', body: JSON.stringify({ tmid }) });

// after - check the setting (exposed via settings/public) first
if (!publicSettings.Threads_enabled) {
  hideThreadUI();
  return;
}
await fetch('/api/v1/chat.readThread', { method: 'POST', body: JSON.stringify({ tmid }) });
Defensive patterns

Strategy: validation

Validate before calling

// Gate thread UI on the feature setting
async function threadsEnabled() {
  const res = await fetch('/api/v1/settings/public');
  const { settings } = await res.json();
  return Boolean(settings.Threads_enabled);
}

Type guard

function isThreadsEnabled(settings) {
  return Boolean(settings && settings.Threads_enabled === true);
}

Try / catch

try {
  await api.readThread({ tmid });
} catch (e) {
  if (e.error === 'error-not-allowed' && /Threads Disabled/.test(e.reason)) {
    hideThreadUI();
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling chat.readThread on a workspace where the Threads feature has been turned off in Administration > Settings.

Common situations: Admin disabled threads; fresh install with threads off by default; feature flag flipped during a deploy.

Related errors


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