Observed behaviour
The bug was originally observed via a reaction-role bot using
The same response was returned by
@discordjs/rest. Across multiple reaction events on the same server:
- Calls targeting users whose highest role is below the bot's highest role consistently returned
200 OKand the role was added. - Calls targeting users whose highest role is at or above the bot's highest role consistently returned:
HTTP 403
{ "code": "MISSING_PERMISSIONS", "message": "You don't have the permissions required to perform this action." }
DELETE. Across the failing cases observed so far, no successful call has been seen — the failure appears consistent rather than intermittent, but this has not been formally tested with a controlled retry loop.
Affected endpoints:
PUT /guilds/{guildId}/members/{userId}/roles/{roleId}DELETE /guilds/{guildId}/members/{userId}/roles/{roleId}
- The bot has the
MANAGE_ROLESpermission. - The role being assigned is below the bot's highest role in the hierarchy.
Reproduction steps
The behavior was discovered on a real server while debugging a reaction-role bot. The pattern below is the suggested controlled test to reproduce it cleanly; the original observation is described under "Actual behavior".
Set up a server with the following role hierarchy (top to bottom):
Then, with the bot:
1. Admin (granted to user A)
2. Bot (granted to the bot, MANAGE_ROLES enabled)
3. Member (granted to user B)
4. Reactable (the role to assign)
5. `@everyone`
- Call
PUT /guilds/{guildId}/members/{userIdOfB}/roles/{reactableRoleId}. - Call
PUT /guilds/{guildId}/members/{userIdOfA}/roles/{reactableRoleId}. - Same pattern for
DELETEon both users.
Details
Summary
PUT /guilds/{guildId}/members/{userId}/roles/{roleId} and the corresponding DELETE endpoint return 403 MISSING_PERMISSIONS when the target user's highest role is at or above the bot's highest role — even when the role being assigned is far below both in the hierarchy. Per the Discord permission model these endpoints should only consider the position of the role being assigned versus the bot's highest role; the target user's hierarchy should not be consulted.
Area
Backend / APIEnvironment
- API base URL:
https://api.fluxer.app - Client tested:
@discordjs/restand directfetch - Bot permissions:
MANAGE_ROLESconfirmed via permission bit inspection (268435456set on the bot's role) - Hierarchy verified visually in the web UI and via
GET /guilds/{id}/roles
Logs
Failed call (raw response body):{
"code" : "MISSING_PERMISSIONS" ,
"message" : "You don't have the permissions required to perform this action."
}GET /guilds/{id}/roles→ 200GET /guilds/{id}/members/{userId}→ 200PATCH /guilds/{id}/members/{userId}with empty body → 200
Hypothesis (not verified — separated from observations above)
The 403 pattern is consistent with a hierarchy check of the form:botMaxRolePosition > targetUserMaxRolePosition // applied incorrectly
addRoleToMember / removeRoleFromMember, which are governed only by the relationship between the bot and the role being assigned.
Relationship to #469
This appears to be a distinct bug from #469:- #469 describes the case where all non-privileged roles share the same position value (e.g.
1), causing the strict comparisonUserMax > role_position(Role)incheck_can_manage_rolesto evaluate1 > 1 = false. The proposed fix adds a tiebreaker by role ID for equal positions. - This issue is observed with distinct role positions: the role being assigned is several positions below both the bot's role and the target user's highest role. The tiebreaker fix from #469 does not apply here because there is no position equality involved — the failure depends on the target user's highest role, not on the assigned role.