RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-subscription

error-invalid-subscription

Error message

Invalid subscription

What it means

saveAutoTranslateSettings requires an existing subscription document joining the calling user to the room (Subscriptions.findOneByRoomIdAndUserId). If the user never joined, left, or was removed from the room, the lookup returns nothing and error-invalid-subscription is thrown before any write. Note a banned user still has a subscription (status 'BANNED'), so this is not the banned-state error.

Source

Thrown at apps/meteor/server/lib/autotranslate/functions/saveSettings.ts:33

	if (!(await hasPermissionAsync(userId, 'auto-translate'))) {
		throw new Meteor.Error('error-action-not-allowed', 'Auto-Translate is not allowed', {
			method: 'autoTranslate.saveSettings',
		});
	}

	check(rid, String);
	check(field, String);
	check(value, String);

	if (['autoTranslate', 'autoTranslateLanguage'].indexOf(field) === -1) {
		throw new Meteor.Error('error-invalid-settings', 'Invalid settings field', {
			method: 'saveAutoTranslateSettings',
		});
	}

	const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, userId);
	if (!subscription) {
		throw new Meteor.Error('error-invalid-subscription', 'Invalid subscription', {
			method: 'saveAutoTranslateSettings',
		});
	}

	let shouldNotifySubscriptionChanged = false;

	switch (field) {
		case 'autoTranslate':
			const room = await Rooms.findE2ERoomById(rid, { projection: { _id: 1 } });
			if (room && value === '1') {
				throw new Meteor.Error('error-e2e-enabled', 'Enabling auto-translation in E2E encrypted rooms is not allowed', {
					method: 'saveAutoTranslateSettings',
				});
			}

			const updateAutoTranslateResponse = await Subscriptions.updateAutoTranslateById(subscription._id, value === '1');
			if (updateAutoTranslateResponse.modifiedCount) {
				shouldNotifySubscriptionChanged = true;

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Verify membership first (the user's subscriptions / rooms list) and join the room if allowed
  2. Refresh the client's subscription cache after join/leave actions
  3. Only expose translate settings for rooms present in the user's subscriptions
Defensive patterns

Strategy: validation

Validate before calling

const subs = await GET '/api/v1/subscriptions.get';
if (!subs.update.some((s) => s.rid === rid)) {
  // user is not in this room - join first or skip saving translate settings
}

Try / catch

try {
  await POST '/api/v1/autotranslate.saveSettings' { roomId: rid, field, value };
} catch (e) {
  if (e.error === 'error-invalid-subscription') {
    // rid is not in the user's subscriptions - refresh and/or join the room
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Saving translate settings for a rid the user is not a member of (pasted rid, room left in another session, removed from a private channel while the client still renders its settings); racing with leaveRoom/removeUser.

Common situations: Stale room lists in long-lived sessions; automation acting on arbitrary room ids; subscription documents removed by moderation tooling.

Related errors


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