{"record":{"id":"a760807e9c2e5735","repo":"RocketChat/Rocket.Chat","slug":"error-action-not-allowed-a76080","errorCode":"error-action-not-allowed","errorMessage":"Editing settings is not allowed","messagePattern":"Editing settings is not allowed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/settings/saveSettings.ts","lineNumber":33,"sourceCode":"\t\t\t\t_id: ISetting['_id'];\n\t\t\t\tvalue: ISetting['value'];\n\t\t\t}[],\n\t\t): Promise<boolean>;\n\t}\n}\n\nMeteor.methods<ServerMethods>({\n\tsaveSettings: twoFactorRequired(async function (\n\t\tparams: {\n\t\t\t_id: ISetting['_id'];\n\t\t\tvalue: ISetting['value'];\n\t\t}[] = [],\n\t) {\n\t\tmethodDeprecationLogger.method('saveSettings', '9.0.0', '/v1/settings');\n\n\t\tconst uid = Meteor.userId();\n\t\tif (uid === null) {\n\t\t\tthrow new Meteor.Error('error-action-not-allowed', 'Editing settings is not allowed', {\n\t\t\t\tmethod: 'saveSetting',\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tawait saveSettingsBulk(uid, params, {\n\t\t\t\tusername: (await Meteor.userAsync())!.username!,\n\t\t\t\tip: this.connection.clientAddress || '',\n\t\t\t\tuseragent: this.connection.httpHeaders['user-agent'] || '',\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof SettingValidationError) {\n\t\t\t\tthrow new Meteor.Error('error-setting-validation-failed', error.message);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn true;","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/settings/saveSettings.ts#L15-L51","documentation":"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`.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wait for authentication: only call `saveSettings` once `Meteor.userId()` is non-null.","Use the REST endpoint `POST /api/v1/settings` with an auth token for headless/programmatic settings updates.","On reconnect, re-run the login flow and then retry the batch.","When debugging, remember the reported method name 'saveSetting' is a copy-paste artifact — the failing call is the bulk method."],"exampleFix":"// before\nMeteor.call('saveSettings', [{ _id, value }]);\n\n// after\nif (Meteor.userId() === null) {\n  // wait for login before flushing pending settings changes\n  return;\n}\nMeteor.call('saveSettings', [{ _id, value }]);","handlingStrategy":"validation","validationCode":"if (Meteor.userId() === null) {\n  // defer the batch until after login\n  return;\n}\nawait Meteor.callAsync('saveSettings', params);","typeGuard":"const isAuthenticated = (): boolean => Meteor.userId() !== null;","tryCatchPattern":"try {\n  await Meteor.callAsync('saveSettings', params);\n} catch (e: any) {\n  if (e?.error === 'error-action-not-allowed' && Meteor.userId() === null) {\n    // authentication failure: note the reported method name is 'saveSetting' (copy-paste)\n  }\n}","preventionTips":["Queue settings changes until the login reactive state confirms a session.","Use POST /api/v1/settings with tokens for headless clients.","Watch for logged-out duplicate tabs sharing stale method calls."],"tags":["meteor","settings","authentication","deprecated"],"backgroundTag":"authentication-required","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}