{"record":{"id":"f2e547c32955052c","repo":"n8n-io/n8n","slug":"owner-cannot-change-role-on-global-owner","errorCode":null,"errorMessage":"Owner cannot change role on global owner","messagePattern":"Owner cannot change role on global owner","errorType":"exception","errorClass":"ForbiddenError","httpStatus":403,"severity":"error","filePath":"packages/cli/src/controllers/users.controller.ts","lineNumber":379,"sourceCode":"\t\t\twhere: { id },\n\t\t\trelations: ['role'],\n\t\t});\n\t\tif (targetUser === null) {\n\t\t\tthrow new NotFoundError(NO_USER);\n\t\t}\n\n\t\tif (\n\t\t\treq.user.role.slug === GLOBAL_ADMIN_ROLE.slug &&\n\t\t\ttargetUser.role.slug === GLOBAL_OWNER_ROLE.slug\n\t\t) {\n\t\t\tthrow new ForbiddenError(NO_ADMIN_ON_OWNER);\n\t\t}\n\n\t\tif (\n\t\t\treq.user.role.slug === GLOBAL_OWNER_ROLE.slug &&\n\t\t\ttargetUser.role.slug === GLOBAL_OWNER_ROLE.slug\n\t\t) {\n\t\t\tthrow new ForbiddenError(NO_OWNER_ON_OWNER);\n\t\t}\n\n\t\tawait this.userService.changeUserRole(targetUser, payload);\n\n\t\tthis.eventService.emit('user-changed-role', {\n\t\t\tuserId: req.user.id,\n\t\t\ttargetUserId: targetUser.id,\n\t\t\ttargetUserNewRole: payload.newRoleName,\n\t\t\tpublicApi: false,\n\t\t});\n\n\t\treturn { success: true };\n\t}\n}\n","sourceCodeStart":361,"sourceCodeEnd":394,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/controllers/users.controller.ts#L361-L394","documentation":"Returned by PATCH /users/:id/role when both requester and target hold the global owner role (GLOBAL_OWNER_ROLE.slug). Even the owner cannot reassign another owner's role through this endpoint. Message is the NO_OWNER_ON_OWNER constant. HTTP 403.","triggerScenarios":"A global owner calls PATCH /users/<another-owner-id>/role; both slug comparisons match GLOBAL_OWNER_ROLE.slug.","commonSituations":"Multi-owner setup; scripted role management that includes peer owners; misunderstanding that owner-to-owner role changes are blocked even for the owner.","solutions":["Reassign ownership through the documented ownership-transfer flow rather than this endpoint.","Filter peer owners out of role-change targets.","Document that owner role transitions are not supported via PATCH /users/:id/role."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function canChangeRole(requesterSlug: string, targetSlug: string) {\n  return !(requesterSlug === 'global:owner' && targetSlug === 'global:owner');\n}\nif (!canChangeRole(reqUser.role.slug, target.role.slug)) {\n  throw new Error('Owner-to-owner role changes are blocked');\n}","typeGuard":"const isOwner = (s: string) => s === 'global:owner';","tryCatchPattern":"try { await fetch(`/rest/users/${id}/role`, { method: 'PATCH', body }); }\ncatch (e) { if (e.statusCode === 403 && /change role on global owner/.test(e.message)) { /* use transfer flow */ } else throw e; }","preventionTips":["Do not target peer owners with PATCH /users/:id/role.","Use the documented ownership-transfer flow for owner reassignment.","Filter owner rows out of role-batch operations."],"tags":["users","rbac","role-change","forbidden","owner","authorization"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}