{"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":246,"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\tconst { statusVisibilityDenied: _ownBlockList, ...preferences } = this.bodyParams.data;\n\n\t\t\tawait saveUserPreferences(userId === this.userId ? this.bodyParams.data : preferences, 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');","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/users.ts#L228-L264","documentation":"Thrown by POST users.setPreferences when the caller passes a userId different from their own authenticated id without holding the edit-other-user-info permission. The endpoint edits user preferences; self-service is always allowed, but touching another user requires that admin permission.","triggerScenarios":"POST users.setPreferences with {userId: 'otherUserId', data: {...}} from an account lacking edit-other-user-info; passing a userId that equals your own is fine, so this fires only on cross-user edits; permission revoked between UI load and save.","commonSituations":"Admin-panel-like tools assuming all logged-in users may edit anyone; cached auth tokens from a demoted admin; passing the target user's id in a field the schema still accepts even when not intended.","solutions":["Omit userId entirely to edit your own preferences","If editing another user is intended, grant the caller edit-other-user-info first (permissions.update)","Check the effective permission via users.info/permissions before showing cross-user edit UI"],"exampleFix":"// before\nawait sdk.post('users.setPreferences', { userId: targetUserId, data }); // fails without permission\n// after\nif (targetUserId !== myUserId) {\n  await requirePermission('edit-other-user-info'); // fails fast client-side\n}\nawait sdk.post('users.setPreferences', { ...(targetUserId !== myUserId && { userId: targetUserId }), data });","handlingStrategy":"validation","validationCode":"if (targetUserId && targetUserId !== myUserId) {\n  const allowed = await hasPermission('edit-other-user-info');\n  if (!allowed) throw new Error('cross-user preferences edit requires edit-other-user-info');\n}\nawait sdk.post('users.setPreferences', { ...(targetUserId && targetUserId !== myUserId ? { userId: targetUserId } : {}), data });","typeGuard":null,"tryCatchPattern":"catch (e) { if (e?.error === 'error-action-not-allowed') retryAsSelfOrRequestPermission(); else throw e; }","preventionTips":["Default to omitting userId for self-edits","Gate cross-user edit UI on a live permission check, not a cached role"],"tags":["rest-api","users","permissions","preferences","authorization"],"backgroundTag":"permission-denied","analyzedSha":"e4b8178b205510181a96ceefee043d0abcd13e5a","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}