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
- Verify membership first (the user's subscriptions / rooms list) and join the room if allowed
- Refresh the client's subscription cache after join/leave actions
- 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
- Only render translate settings for rooms present in the user's subscriptions
- Refresh the subscription cache after join/leave events
- Treat pasted room ids as untrusted input in automation
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
- error-e2e-enabled
- User is not in this room
- User is already banned from this room
- Room not found
- Subscription not found
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/0a1f361f330ab810.
Report an issue: GitHub.