When creating multiple ordered roles in a for loop I'm creating a role, getting a bookmark role position, and then setting the new role position to bookmark role position -1. Somehow, roles manage to be moved incorrectly, move other roles, which were pre-existing and in general not work.
for missing_role in missing_roles:
role = discord.utils.get(member.guild.roles, name=f'{missing_role} {skills[missing_role.lower()]}')
if role is not None:
new_roles.append(role)
else:
role = await member.guild.create_role(name=f"{missing_role} {skills[missing_role.lower()]}", color=Colour(value=int(ROLE_COLORS[missing_role.lower()], 16)), reason='Updating skills')
closest_position = discord.utils.get(member.guild.roles, name=f'{missing_role} Bookmark').position
print(member.guild.roles)
print(f'{role} {role.position} {closest_position-1}')
await role.edit(position=closest_position-1)
Was expecting it to go from this:

To this:

Results are +- different each time
Went from this:

To this:

Things, like bookmarks shouldn't be moved at all.
Log from the prints:
quick_log.txt
intents = discord.Intents().default()
intents.members = True
This is likely due to Discord's role and channel position APIs being eventually consistent.
Any way around this issue?
Any way around this issue?
This is a Discord limitation.
That said, updating the position of all roles - one by one - to incremental values should get them consistent on the server, then updating the incorrectly positioned roles may solve this, and has done so for me in the past. There is no guarantee that this will not break again.
Create all your roles then use edit_role_positions. This edits all the role positions at once and sidesteps the cache-out-of-date-discord-out-of-date issue
I'll try doing that.
Quick question. Why was the code I provide moving roles that it shouldn't?
Discord doesn't provide a way to move a singular role at once- you actually edit the positions of every role. Discord.py uses it's internal cache to calculate the new role positions for everything, but when you do that in a loop, the positions get rapidly out of date and fuckery happens. Using edit_role_positions does this all at once, avoiding cache, and fuckery.
Updated some code, at least now the roles are in the correct order, but not correct positions, and the positions seem to +- shift randomly each time I run it.
Code used:
for missing_role in missing_roles:
role = await member.guild.create_role(name=f"{missing_role} {skills[missing_role.lower()]}", color=Colour(value=int(ROLE_COLORS[missing_role.lower()], 16)), reason='Updating skills')
new_roles.append(role)
for role in new_roles:
result = re.search('^(Alchemy|Combat|Enchanting|Farming|Fishing|Foraging|Mining|Taming) ([0-9]+)', role.name)
closest_position = discord.utils.get(member.guild.roles, name=f'{result.group(1)} Bookmark').position
new_roles2[role] = closest_position - 1
print(new_roles2)
await member.guild.edit_role_positions(new_roles2)
First run:

Deleted the roles and tried again:

The position shifts each run.
Well, this sucks. Got rate-limited and have no choice but to retry experimenting in 5 hours...
EDIT: Was thinking about an upcoming event for me and said the wrong amount of time.
Most helpful comment
Create all your roles then use edit_role_positions. This edits all the role positions at once and sidesteps the cache-out-of-date-discord-out-of-date issue