Files
ChatGPT-Discord-Bot/docs/DISCORD_MESSAGE_ERROR_FIX.md
cauvang32 9c180bdd89 Refactor OpenAI utilities and remove Python executor
- Removed the `analyze_data_file` function from tool definitions to streamline functionality.
- Enhanced the `execute_python_code` function description to clarify auto-installation of packages and file handling.
- Deleted the `python_executor.py` module to simplify the codebase and improve maintainability.
- Introduced a new `token_counter.py` module for efficient token counting for OpenAI API requests, including support for Discord image links and cost estimation.
2025-10-02 21:49:48 +07:00

5.6 KiB

Discord Message Error Fix - "Unknown Message"

🐛 Problem

When deleting files or canceling deletion, the bot was throwing this error:

404 Not Found (error code: 10008): Unknown Message

🔍 Root Cause

The error occurred in the ConfirmDeleteView class when trying to edit ephemeral messages after they had already been responded to.

Technical Details:

  1. User clicks delete confirmation button
  2. Bot sends a followup message with interaction.followup.send()
  3. Bot then tries to edit the original message with interaction.message.edit()
  4. Discord returns 404 because ephemeral messages can't be edited after a followup is sent

Discord Behavior:

  • Ephemeral messages (only visible to one user) have limited lifetime
  • Once you use interaction.followup.send(), the original interaction message may become inaccessible
  • Attempting to edit it causes a 404 Not Found error

Solution

Wrapped all interaction.message.edit() calls in try-except blocks to gracefully handle cases where the message is no longer accessible.

Changes Made

1. Fixed Delete Confirmation (lines ~390-420)

Before:

await interaction.followup.send(embed=embed, ephemeral=True)

# Disable all buttons
for item in self.children:
    item.disabled = True
await interaction.message.edit(view=self)  # ❌ Could fail!

After:

await interaction.followup.send(embed=embed, ephemeral=True)

# Disable all buttons (try to edit, but ignore if message is gone)
try:
    for item in self.children:
        item.disabled = True
    await interaction.message.edit(view=self)
except discord.errors.NotFound:
    # Message was already deleted or is ephemeral and expired
    pass
except Exception as edit_error:
    logger.debug(f"Could not edit message after deletion: {edit_error}")

2. Fixed Cancel Button (lines ~425-445)

Before:

await interaction.response.send_message(embed=embed, ephemeral=True)

# Disable all buttons
for item in self.children:
    item.disabled = True
await interaction.message.edit(view=self)  # ❌ Could fail!

After:

await interaction.response.send_message(embed=embed, ephemeral=True)

# Disable all buttons (try to edit, but ignore if message is gone)
try:
    for item in self.children:
        item.disabled = True
    await interaction.message.edit(view=self)
except discord.errors.NotFound:
    # Message was already deleted or is ephemeral and expired
    pass
except Exception as edit_error:
    logger.debug(f"Could not edit message after cancellation: {edit_error}")

🎯 Benefits

User Experience

  • No more error messages in logs
  • File deletion still works perfectly
  • Cancel button still works perfectly
  • Buttons are disabled when possible
  • Graceful degradation when message is gone

Code Quality

  • Proper error handling
  • More resilient to Discord API quirks
  • Debug logging for troubleshooting
  • Follows best practices for ephemeral messages

📊 Error Handling Strategy

Scenario Old Behavior New Behavior
Message exists Disables buttons Disables buttons
Message expired Crashes with error Silently continues
Network error Crashes with error Logs and continues
Permission error Crashes with error Logs and continues

🔍 Why This Happens

Discord Ephemeral Message Lifecycle

User clicks button
    ↓
interaction.response.defer() or send_message()
    ↓
[Message is active for ~15 minutes]
    ↓
interaction.followup.send()
    ↓
[Original interaction may expire]
    ↓
interaction.message.edit()  ← Can fail here!

Key Points

  1. Ephemeral messages are only visible to one user
  2. Interaction tokens expire after 15 minutes
  3. Followup messages create new messages, don't extend the original
  4. Editing after followup may fail if interaction expired

🧪 Testing

Test Case 1: Delete File (Success)

1. User uploads file
2. User runs /files
3. User selects file from dropdown
4. User clicks "Delete" button
5. User clicks "Yes, Delete"
6. User clicks "Click Again to Confirm"
7. ✅ File deleted, no errors

Test Case 2: Delete File (Cancel)

1. User uploads file
2. User runs /files
3. User selects file from dropdown
4. User clicks "Delete" button
5. User clicks "Cancel"
6. ✅ Deletion cancelled, no errors

Test Case 3: Timeout Scenario

1. User runs /files
2. User waits 10+ minutes
3. User clicks button
4. ✅ Graceful handling, no crash

📝 Code Pattern for Future

When working with ephemeral messages and followups:

# ✅ GOOD: Always wrap message edits in try-except
try:
    await interaction.message.edit(view=view)
except discord.errors.NotFound:
    pass  # Message expired, that's okay
except Exception as e:
    logger.debug(f"Could not edit message: {e}")

# ❌ BAD: Assuming message is always editable
await interaction.message.edit(view=view)  # Can crash!

🎉 Result

The error is now handled gracefully:

  • No more "Unknown Message" errors in logs
  • File deletion works reliably
  • Cancel button works reliably
  • Better user experience overall

Date: October 2, 2025 Version: 1.2.1 Status: Fixed