Discord.js: Bot gives the role, and then removes it

Created on 30 Sep 2017  Â·  5Comments  Â·  Source: discordjs/discord.js

Bot gives the role, and then removes it (the same role).
image

My code:

const Discord = require("discord.js");
const bot = new Discord.Client();

bot.on('ready', () => {
    const guild = bot.guilds.get('249828546153938955');
    const member = guild.member(bot.users.get('146770757463179264'));
    if(member) {
           member.removeRoles('363796105357557761'); 
               member.addRole('363796178304761866');
    }
});
  • discord.js version: 11.2.1
  • node.js version: 8.4.0
  • Operating system: Win10
  • Priority this issue should have – I don't know ^_^
    If it's bug - may be middle :)

P.S. On your Discord server did not help me with this issue, so I suspect that is a bug.

question (please use Discord instead)

Most helpful comment

Your issue here is a mixture of a race condition and the how the lib handles removing or adding of multiple roles.

That being: Modifying the cached roles of the member and them patching all of them to the api (Equal to GuildMember#setRoles). (lib handling part)

This removes your newly added role, if the role gets added before patching the others. (race condition part)

As a solution I propose that you use GuildMember#setRoles because you want to add and remove roles at the same time.
Easiest way would probably to make a set of the current role id's and then remove and add as you wish. Before passing it to setRoles simply spread it.

Small example:

const roles = new Set(member.roles.keyArray());
roles.add('someRoleId');
roles.delete('someOtherRoleId');
member.setRoles([...roles]);

And as a side note, which is not really relevant to your current issue, but could be your next:
GuildMember#removeRoles takes an array or collection of role ids or role objects.
Passing a single string will just be ignored duo the way the method iterates the string.

All 5 comments

Can you please fill out the issue template?
Especially this part:
grafik

Sorry, added.

Your issue here is a mixture of a race condition and the how the lib handles removing or adding of multiple roles.

That being: Modifying the cached roles of the member and them patching all of them to the api (Equal to GuildMember#setRoles). (lib handling part)

This removes your newly added role, if the role gets added before patching the others. (race condition part)

As a solution I propose that you use GuildMember#setRoles because you want to add and remove roles at the same time.
Easiest way would probably to make a set of the current role id's and then remove and add as you wish. Before passing it to setRoles simply spread it.

Small example:

const roles = new Set(member.roles.keyArray());
roles.add('someRoleId');
roles.delete('someOtherRoleId');
member.setRoles([...roles]);

And as a side note, which is not really relevant to your current issue, but could be your next:
GuildMember#removeRoles takes an array or collection of role ids or role objects.
Passing a single string will just be ignored duo the way the method iterates the string.

If that is the case the documentation of GuildMember#addRoles and GuildMember#removeRoles can be improved to reflect this behaviour and it should recommend using setRoles instead.

Any asynchronous operations are supposed to be awaited; if await was used in the example code, it would work without issue.

However, this race issue could become more prevalent regardless of which method is being used. Any attempts to set roles in parallel (which could occur; imagine two commands or events dealing with roles being processed in parallel) will cause this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Lombra picture Lombra  Â·  3Comments

iCrawl picture iCrawl  Â·  3Comments

Blumlaut picture Blumlaut  Â·  3Comments

Brawaru picture Brawaru  Â·  3Comments

tom-barnes picture tom-barnes  Â·  3Comments