Why Discord Bot Modal Submissions Fail With 3-Second Interaction Timeout
🔍 WiseChecker

Why Discord Bot Modal Submissions Fail With 3-Second Interaction Timeout

When a Discord bot sends a modal to a user and the user takes longer than three seconds to submit it, the interaction fails and the bot cannot process the submission. This happens because Discord automatically invalidates any bot interaction that is not acknowledged within a 3-second window. This article explains the technical reason behind this timeout, provides the correct steps to handle modal submissions, and covers related failure patterns that bot developers commonly encounter.

Key Takeaways: Handling Discord Bot Modal Timeouts

  • Defer the interaction within 3 seconds: Use interaction.deferReply() or interaction.deferUpdate() to acknowledge the modal submission and buy time for processing.
  • Use ephemeral follow-ups: After deferring, send the actual response with interaction.followUp() to avoid a second timeout.
  • Check modal custom IDs: Ensure the bot listens for the exact custom ID string defined in the modal to prevent unhandled interactions.

ADVERTISEMENT

Why Discord Enforces a 3-Second Interaction Timeout

Discord’s interaction system is designed for real-time responsiveness. When a user clicks a button, selects a menu option, or submits a modal, Discord expects the bot to acknowledge that interaction within three seconds. If the bot does not respond in time, Discord considers the interaction expired and the bot receives an HTTP 400 error with the message “interaction failed.” This timeout is not a bug — it is a deliberate design choice to prevent bots from holding user interfaces open indefinitely.

The 3-second limit applies to the initial acknowledgment only. After the bot acknowledges the interaction, it has up to 15 minutes to send follow-up messages using the interaction token. The key is that the acknowledgment must happen within the first three seconds. Modal submissions are particularly prone to this timeout because the bot often needs to validate data, query a database, or call an external API before responding. If any of these operations take longer than three seconds, the interaction fails silently from the user’s perspective — the modal closes but no feedback appears.

Another common cause is using interaction.reply() directly with a long-running operation. Discord’s reply() method both acknowledges and sends a response in one call. If the reply content is not ready within three seconds, the entire interaction fails. The correct approach is to separate acknowledgment from response using deferral methods.

Steps to Fix Modal Submission Timeouts in Discord Bots

The solution involves two parts: acknowledging the interaction within three seconds and then sending the actual response as a follow-up. The following steps assume you are using discord.js version 14 or later and have a basic bot that can receive modals.

Step 1: Defer the Modal Submission Immediately

  1. Use interaction.deferReply() for new messages
    Inside your modal submit handler, call await interaction.deferReply({ ephemeral: true }) as the first line. This tells Discord that the bot received the interaction and will respond shortly. The ephemeral: true option hides the response from other users in the channel.
  2. Use interaction.deferUpdate() for existing messages
    If the modal was triggered from a button or select menu on an existing message, use await interaction.deferUpdate() instead. This acknowledges the interaction without sending a new message. You can later edit the original message with the results.
  3. Add error handling for failed deferrals
    Wrap the deferral in a try-catch block. If the deferral throws an error (for example, because the interaction already expired), log it and exit the handler gracefully. Example: try { await interaction.deferReply(); } catch (e) { console.error('Defer failed:', e); return; }

Step 2: Run Your Processing Logic

  1. Perform data validation and external calls
    After deferring, you have up to 15 minutes to complete your logic. Validate modal fields, query a database, or call a REST API. The user sees a loading state on the Discord client while waiting.
  2. Use interaction.followUp() to send the response
    Once processing is complete, send the result with await interaction.followUp({ content: 'Your submission was saved.', ephemeral: true }). This sends a new message as a follow-up to the deferred interaction. Do not use interaction.reply() after deferring — it will throw an error.

Step 3: Match the Custom ID Correctly

  1. Set a unique custom ID when creating the modal
    When you create the modal object, assign a string to the customId property, for example new ModalBuilder().setCustomId('feedback_modal'). This ID must be unique within your bot’s scope.
  2. Listen for that exact custom ID in the handler
    In your interaction create event, filter by interaction.customId === 'feedback_modal'. If the ID does not match, the bot ignores the submission and the interaction times out. Use a consistent naming convention to avoid typos.

ADVERTISEMENT

If Discord Bot Modals Still Time Out After the Main Fix

Bot Goes Offline During Modal Processing

If your bot crashes or disconnects between the deferral and the follow-up, the interaction will time out after 15 minutes. The user sees no error message. To prevent this, add a fallback that edits the deferred response to a generic error message if the main logic throws an unhandled exception. Use a try-catch around the entire processing block and call interaction.editReply() inside the catch.

Modal Closes but No Response Appears

This usually means the bot never called deferReply() or deferUpdate(), or the deferral call itself took longer than three seconds. Check that your handler does not contain any synchronous blocking operations — for example, fs.readFileSync() or a long for loop — before the deferral. Move all heavy work after the deferral.

Multiple Modals Open at Once

Discord allows only one modal to be open per user per client. If a user opens a second modal while the first is still active, the first modal is dismissed and its interaction is invalidated. The bot may receive a submission for the second modal but the first one is lost. Educate users to submit one modal at a time, or implement a cooldown that prevents opening a new modal until the previous one is resolved.

Discord Bot Interaction Acknowledgment Methods: Defer vs Reply vs Follow-Up

Method DeferReply Reply
Purpose Acknowledge interaction without sending a response immediately Acknowledge interaction and send a response in one call
Time limit 3 seconds to call; 15 minutes to follow up 3 seconds to complete the entire call
Response type Must use followUp() or editReply() after deferring Response is sent immediately; no follow-up needed
Use case Long database queries, file uploads, external API calls Instant responses like simple confirmations or errors

Discord bot modal submissions fail with a 3-second interaction timeout because the bot does not acknowledge the interaction within the required window. By calling interaction.deferReply() or interaction.deferUpdate() as the first action in your modal handler, you extend the response window to 15 minutes. After processing, use interaction.followUp() to send the result. For advanced reliability, wrap your handler in a try-catch and provide a fallback message if the main logic fails. Test your bot with a slow network simulation to confirm the deferral works before any blocking operations.

ADVERTISEMENT