pycord icon indicating copy to clipboard operation
pycord copied to clipboard

AttributeError when attempting to edit timed out view messages

Open iqnite opened this issue 7 months ago • 2 comments

Summary

Calling View.message.edit on timeout raises an AttributeError

Reproduction Steps

Call View.message.edit in View.on_timeout without interacting with any UI component.

Minimal Reproducible Code

@discord.slash_command(name="testcmd", description="Test.")
async def test_command(self, ctx: discord.ApplicationContext):
    view = TestView()
    await ctx.respond(view=view)


class TestView(discord.ui.View):
    def __init__(self):
        super().__init__(timeout=10)

    @discord.ui.button(label="Test Button")
    async def test_button_callback(self, _, interaction: discord.Interaction):
        await interaction.respond("OK")
        await self.message.edit(content="Button clicked!")

    async def on_timeout(self):
        await self.message.edit(content="Timed out.")

Expected Results

Clicking the Test Button should edit the message with the view and send an OK message. After 10 seconds without activity, the message with the view should be edited to Timed out.

Actual Results

Clicking the button and waiting 10 seconds provides the expected result. If the view times out and the button has not been clicked before, the following error is raised:

Task exception was never retrieved
future: <Task finished name='discord-ui-view-timeout-c00e25e3df45277117584b95a880298e' coro=<TestView.on_timeout() done, defined at C:\Users\iqnit\Repos\eggsplode\eggsplode\cogs\misc.py:77> exception=AttributeError("'NoneType' object has no attribute 'edit'")>
Traceback (most recent call last):
  File "C:\Users\iqnit\Repos\eggsplode\eggsplode\cogs\misc.py", line 78, in on_timeout
    await self.message.edit(content="Timed out.")
          ^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'edit'

Intents

I do not pass any discord.Intents class and go by the defaults.

System Information

  • Python v3.12.7-final
  • py-cord v2.6.1-final
  • aiohttp v3.11.18
  • system info: Windows 11 10.0.26120

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

The error does not occur if View.message is set manually. The following change fixes the code:

async def test_command(self, ctx: discord.ApplicationContext):
    view = TestView()
-   await ctx.respond(view=view)
+   view.message = await ctx.respond(view=view)

Also, while it might be irrelevant, VS Code's type checker marks View.message.edit as potential AttributeArror: "edit" is not a known attribute of "None" reportOptionalMemberAccess

iqnite avatar May 25 '25 19:05 iqnite

First mention: https://github.com/Pycord-Development/pycord/pull/2707#issuecomment-2907819019

iqnite avatar May 25 '25 19:05 iqnite

The reason is InteractionResponse.send_message (first response method if you did not defer) did not receive a message object from Discord - while it returns the same Interaction used, up until recently Discord did not return a message object and as such View.message is not set in that scenario. View.message is set if you defer -> respond, use an edit method, or used a followup method - your example working code only works by complete coincidence because Interaction.edit exists. What you are requesting is possible in #2711

NeloBlivion avatar May 31 '25 03:05 NeloBlivion

fixed in #2267

Lumabots avatar Oct 13 '25 11:10 Lumabots