{"record":{"id":"3162458f29d65b14","repo":"RocketChat/Rocket.Chat","slug":"error-action-not-allowed-316245","errorCode":"error-action-not-allowed","errorMessage":"Editing user is not allowed","messagePattern":"Editing user is not allowed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/users.ts","lineNumber":243,"sourceCode":"\t)\n\t.post(\n\t\t'users.setPreferences',\n\t\t{\n\t\t\tauthRequired: true,\n\t\t\tbody: isUsersSetPreferencesParamsPOST,\n\t\t\tresponse: {\n\t\t\t\t200: userObjectResponse,\n\t\t\t\t400: validateBadRequestErrorResponse,\n\t\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t\t},\n\t\t},\n\t\tasync function action() {\n\t\t\tif (\n\t\t\t\tthis.bodyParams.userId &&\n\t\t\t\tthis.bodyParams.userId !== this.userId &&\n\t\t\t\t!(await hasPermissionAsync(this.user, 'edit-other-user-info'))\n\t\t\t) {\n\t\t\t\tthrow new Meteor.Error('error-action-not-allowed', 'Editing user is not allowed');\n\t\t\t}\n\t\t\tconst userId = this.bodyParams.userId ? this.bodyParams.userId : this.userId;\n\t\t\tif (!(await Users.findOneById(userId))) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-user', 'The optional \"userId\" param provided does not match any users');\n\t\t\t}\n\n\t\t\tawait saveUserPreferences(this.bodyParams.data, userId);\n\t\t\tconst user = await Users.findOneById(userId, {\n\t\t\t\tprojection: {\n\t\t\t\t\t'settings.preferences': 1,\n\t\t\t\t\t'language': 1,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\treturn API.v1.failure('User not found');\n\t\t\t}\n","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/users.ts#L225-L261","documentation":"Thrown by the users.setPreferences endpoint when the caller supplies a bodyParams.userId that differs from their own authenticated userId and they lack the 'edit-other-user-info' permission.","triggerScenarios":"POST users.setPreferences with { userId: '<other-user>' } while the authenticated user does not have the edit-other-user-info permission.","commonSituations":"A non-admin client tries to update another user's preferences; permission role was removed; testing with a wrong token.","solutions":["Omit userId to edit your own preferences, or authenticate as a user holding edit-other-user-info.","Grant the edit-other-user-info role to the caller if cross-user edits are intended.","Confirm the userId you are sending is actually your own when self-editing."],"exampleFix":"// before\nawait POST('users.setPreferences', { userId: otherUserId, data: prefs });\n\n// after - self-edit (no permission needed)\nawait POST('users.setPreferences', { data: prefs });","handlingStrategy":"validation","validationCode":"// Only send userId when editing another user AND you hold the permission\nconst targetUserId = (body.userId && body.userId !== me._id && hasRole('edit-other-user-info'))\n  ? body.userId\n  : undefined;\nawait POST('users.setPreferences', { data: prefs, ...(targetUserId ? { userId: targetUserId } : {}) });","typeGuard":"null","tryCatchPattern":"try {\n  await POST('users.setPreferences', body);\n} catch (e) {\n  if (isMeteorError(e, 'error-action-not-allowed')) {\n    // drop userId and retry as self-edit, or escalate permissions\n  } else { throw e; }\n}","preventionTips":["Default to omitting userId; only add it when cross-user editing is explicitly authorized.","Check the caller's permissions in the UI before exposing cross-user controls."],"tags":["users","permissions","authorization","api"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}