discord.py
discord.py copied to clipboard
Multiple selects error
Summary
master commit breaks multiple selects
Reproduction Steps
this commit provides global state for Select object
Minimal Reproducible Code
No response
Expected Results
No global state
Actual Results
global state
Intents
...
System Information
...
Checklist
- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.
Additional Context
No response
I have this problem too :/
Could you give more context to the issue? The actual behavior you're experiencing? Code to reproduce it?
The commit goal was to remove global state, which I believe it did successfully, solving race conditions as described in the PR. I'm fairly sure I tested this before submitting the PR, just tested again and I'm not experiencing any issues.
Test code:
# generate 4 options labeled 1-4
options = [SelectOption(label=f'option {n}') for n in range(1, 5)]
class Select(ui.Select):
async def callback(self, interaction: Interaction):
original = self.values[0]
await interaction.response.defer()
await asyncio.sleep(10)
after_sleep = self.values[0]
await interaction.followup.send(f'{original = }\n{after_sleep = }')
class View(ui.View):
def __init__(self):
super().__init__()
self.add_item(Select(options=options[:2])) # first select has options 1 and 2
self.add_item(Select(options=options[2:])) # second select has options 3 and 4
In quick succession, all before the first followup was sent, I selected in order:
"option 1" from the first select
"option 4" from the second select
"option 2" from the first select
And these were the resulting followups:

EDIT: I also repeated this test with both selects using @ui.select() inside the view and with one a subclass, one decorated. Both gave the same result as the initial test where both were using the subclass.
import sys
import discord
from discord import Intents
from discord.ext import commands
bot = commands.Bot(command_prefix='/', intents=Intents.all())
@bot.tree.command()
async def create_event(interaction: discord.Interaction):
'''
Creates embed message for event on server
'''
event_category = list(
filter(lambda x: 'event' in x.name.lower(), interaction.guild.categories)
)[0]
class TestModal(discord.ui.Modal, title='Test Modal'):
text_channel = discord.ui.Select(
options=[
discord.SelectOption(label=channel.name, value=channel.id)
for channel in event_category.text_channels
],
placeholder='Channel for event message',
)
voice_channel = discord.ui.Select(
options=[
discord.SelectOption(label=channel.name, value=channel.id)
for channel in event_category.voice_channels
],
min_values=0,
placeholder='Voice channel for auto connect button',
)
async def on_submit(self, interaction: discord.Interaction):
await interaction.guild.get_channel(int(self.text_channel.values[0])).send(
content='test',
)
await interaction.response.send_message('message added', ephemeral=True)
await interaction.response.send_modal(TestModal())
def run():
bot.run('TOKEN')
if __name__ == '__main__':
run()
sys.exit(0)
Error:
Traceback (most recent call last):
File "/home/randomneo/.virtualenvs/discord-edge/lib/python3.10/site-packages/discord/ui/modal.py", line 184, in _scheduled_task
await self.on_submit(interaction)
File "/home/randomneo/projects/personal/fucking-discord/main.py", line 37, in on_submit
await interaction.guild.get_channel(int(self.text_channel.values[0])).send(
IndexError: list index out of range
If redefine function Modal._refresh to prevent calling of second item._refresh_state then no error
def _refresh(self, components: Sequence[ModalSubmitComponentInteractionDataPayload]) -> None:
for component in components:
if component['type'] == 1:
self._refresh(component['components'])
return
else:
item = find(lambda i: i.custom_id == component['custom_id'], self._children) # type: ignore
if item is None:
_log.debug("Modal interaction referencing unknown item custom_id %s. Discarding", component['custom_id'])
continue
item._refresh_state(component) # type: ignore
So this is specifically regarding modals. All selects get the last one's values, instead of their own. The error you're getting is because the last select is voice channels, which you selected no options for. I guess this is confirmed, then.
@Puncher1 on which version/commit are you running? Issue reproducible after this commit
I am also experiencing this bug in a modal select All selects get the value of the last select
@Randomneo
~~I'm running it on the latest commit, when I list my packages with pip list I get this~~
Can confirm this bug. It tries to send the message to the voice channel. It just doesn't throw any errors. Sorry for the confusion