RocketChat/Rocket.Chat · error · Meteor.Error

error-action-not-allowed

error-action-not-allowed

Error message

Editing settings is not allowed

What it means

The bulk `saveSettings` Meteor method throws `error-action-not-allowed` when `Meteor.userId()` is null — the caller is not authenticated. Note the error metadata misleadingly reports `method: 'saveSetting'` (single) even though the failing method is `saveSettings`; the method is also deprecated since 9.0.0 in favor of REST `POST /v1/settings`.

Solutions

  1. Wait for authentication: only call `saveSettings` once `Meteor.userId()` is non-null.
  2. Use the REST endpoint `POST /api/v1/settings` with an auth token for headless/programmatic settings updates.
  3. On reconnect, re-run the login flow and then retry the batch.
  4. When debugging, remember the reported method name 'saveSetting' is a copy-paste artifact — the failing call is the bulk method.

Example fix

// before
Meteor.call('saveSettings', [{ _id, value }]);

// after
if (Meteor.userId() === null) {
  // wait for login before flushing pending settings changes
  return;
}
Meteor.call('saveSettings', [{ _id, value }]);
Defensive patterns

Strategy: validation

Validate before calling

if (Meteor.userId() === null) {
  // defer the batch until after login
  return;
}
await Meteor.callAsync('saveSettings', params);

Type guard

const isAuthenticated = (): boolean => Meteor.userId() !== null;

Try / catch

try {
  await Meteor.callAsync('saveSettings', params);
} catch (e: any) {
  if (e?.error === 'error-action-not-allowed' && Meteor.userId() === null) {
    // authentication failure: note the reported method name is 'saveSetting' (copy-paste)
  }
}

Prevention

When it happens

Trigger: Calling `Meteor.call('saveSettings', [{ _id, value }, ...])` from an unauthenticated DDP connection: before login completes, after logout, after an expired resume token reconnect, or from server code without a user context.

Common situations: Settings forms submitted during page load before the login reactive chain finishes; tokens invalidated server-side while the client keeps the connection; scripts calling the DDP method directly without establishing a session.

Related errors


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

Appendix: source

Thrown at apps/meteor/server/meteor-methods/settings/saveSettings.ts:33

				_id: ISetting['_id'];
				value: ISetting['value'];
			}[],
		): Promise<boolean>;
	}
}

Meteor.methods<ServerMethods>({
	saveSettings: twoFactorRequired(async function (
		params: {
			_id: ISetting['_id'];
			value: ISetting['value'];
		}[] = [],
	) {
		methodDeprecationLogger.method('saveSettings', '9.0.0', '/v1/settings');

		const uid = Meteor.userId();
		if (uid === null) {
			throw new Meteor.Error('error-action-not-allowed', 'Editing settings is not allowed', {
				method: 'saveSetting',
			});
		}

		try {
			await saveSettingsBulk(uid, params, {
				username: (await Meteor.userAsync())!.username!,
				ip: this.connection.clientAddress || '',
				useragent: this.connection.httpHeaders['user-agent'] || '',
			});
		} catch (error) {
			if (error instanceof SettingValidationError) {
				throw new Meteor.Error('error-setting-validation-failed', error.message);
			}
			throw error;
		}

		return true;

View on GitHub (pinned to b2c16d5842)