Por que envios de modal do Discord falham com timeout de 3 segundos
🔍 WiseChecker

Por que envios de modal do Discord falham com timeout de 3 segundos

Quando um bot do Discord envia um modal para um usuário e o usuário demora mais de três segundos para enviá-lo, a interação falha e o bot não consegue processar o envio. Isso acontece porque o Discord invalida automaticamente qualquer interação de bot que não seja reconhecida em uma janela de 3 segundos. Este artigo explica o motivo técnico por trás desse timeout, fornece as etapas corretas para lidar com envios de modal e aborda padrões de falha relacionados que desenvolvedores de bots encontram com frequência.

Principais conclusões: Como lidar com timeouts de modal do Discord

  • Adie a interação dentro de 3 segundos: Use interaction.deferReply() ou interaction.deferUpdate() para reconhecer o envio do modal e ganhar tempo para processamento.
  • Use follow-ups efêmeros: Após adiar, envie a resposta real com interaction.followUp() para evitar um segundo timeout.
  • Verifique os custom IDs do modal: Certifique-se de que o bot escuta exatamente o string de custom ID definido no modal para evitar interações não tratadas.

ADVERTISEMENT

Por que o Discord impõe um timeout de 3 segundos para interações

O sistema de interação do Discord foi projetado para capacidade de resposta em tempo real. Quando um usuário clica em um botão, seleciona uma opção de menu ou envia um modal, o Discord espera que o bot reconheça essa interação em até três segundos. Se o bot não responder a tempo, o Discord considera a interação expirada e o bot recebe um erro HTTP 400 com a mensagem “interaction failed”. Esse timeout não é um bug — é uma escolha de design deliberada para evitar que bots mantenham interfaces de usuário abertas indefinidamente.

O limite de 3 segundos se aplica apenas ao reconhecimento inicial. Após o bot reconhecer a interação, ele tem até 15 minutos para enviar mensagens de acompanhamento usando o token da interação. O ponto chave é que o reconhecimento deve acontecer dentro dos primeiros três segundos. Envios de modal são particularmente propensos a esse timeout porque o bot muitas vezes precisa validar dados, consultar um banco de dados ou chamar uma API externa antes de responder. Se qualquer uma dessas operações levar mais de três segundos, a interação falha silenciosamente da perspectiva do usuário — o modal fecha, mas nenhum feedback aparece.

Outra causa comum é usar interaction.reply() diretamente com uma operação de longa duração. O método reply() do Discord reconhece e envia uma resposta em uma única chamada. Se o conteúdo da resposta não estiver pronto em três segundos, toda a interação falha. A abordagem correta é separar o reconhecimento da resposta usando métodos de adiamento.

Etapas para corrigir timeouts de envio de modal em bots do Discord

A solução envolve duas partes: reconhecer a interação dentro de três segundos e depois enviar a resposta real como um follow-up. As etapas a seguir assumem que você está usando discord.js versão 14 ou posterior e tem um bot básico que pode receber modais.

Passo 1: Adie o envio do modal imediatamente

  1. Use interaction.deferReply() para novas mensagens
    Dentro do seu manipulador de envio de modal, chame await interaction.deferReply({ ephemeral: true }) como a primeira linha. Isso informa ao Discord que o bot recebeu a interação e responderá em breve. A opção ephemeral: true oculta a resposta de outros usuários no canal.
  2. Use interaction.deferUpdate() para mensagens existentes
    Se o modal foi acionado a partir de um botão ou menu de seleção em uma mensagem existente, use await interaction.deferUpdate() em vez disso. Isso reconhece a interação sem enviar uma nova mensagem. Você pode editar a mensagem original com os resultados posteriormente.
  3. Adicione tratamento de erros para adiamentos com falha
    Envolva o adiamento em um bloco try-catch. Se o adiamento lançar um erro (por exemplo, porque a interação já expirou), registre-o e saia do manipulador graciosamente. Exemplo: try { await interaction.deferReply(); } catch (e) { console.error('Adiamento falhou:', e); return; }

Passo 2: Execute sua lógica de processamento

  1. Realize validação de dados e chamadas externas
    Após adiar, você tem até 15 minutos para concluir sua lógica. Valide campos do modal, consulte um banco de dados ou chame uma API REST. O usuário vê um estado de carregamento no cliente do Discord enquanto espera.
  2. Use interaction.followUp() para enviar a resposta
    Assim que o processamento for concluído, envie o resultado com await interaction.followUp({ content: 'Seu envio foi salvo.', ephemeral: true }). Isso envia uma nova mensagem como follow-up da interação adiada. Não use interaction.reply() após adiar — isso lançará um erro.

Passo 3: Corresponda o Custom ID corretamente

  1. Defina um custom ID único ao criar o modal
    Ao criar o objeto modal, atribua um string à propriedade customId, por exemplo new ModalBuilder().setCustomId('feedback_modal'). Esse ID deve ser único no escopo do seu bot.
  2. Escute exatamente esse custom ID no manipulador
    No seu evento de criação de interação, filtre por interaction.customId === 'feedback_modal'. Se o ID não corresponder, o bot ignora o envio e a interação expira. Use uma convenção de nomenclatura consistente para evitar erros de digitação.

ADVERTISEMENT

Se os modais do Discord ainda expirarem após a correção principal

Bot fica offline durante o processamento do modal

Se o seu bot travar ou desconectar entre o adiamento e o follow-up, a interação expirará após 15 minutos. O usuário não vê nenhuma mensagem de erro. Para evitar isso, adicione um fallback que edite a resposta adiada para uma mensagem de erro genérica se a lógica principal lançar uma exceção não tratada. Use um try-catch em todo o bloco de processamento e chame interaction.editReply() dentro do catch.

Modal fecha, mas nenhuma resposta aparece

Isso geralmente significa que o bot nunca chamou deferReply() ou deferUpdate(), ou a própria chamada de adiamento levou mais de três segundos. Verifique se o seu manipulador não contém operações síncronas bloqueantes — por exemplo, fs.readFileSync() ou um loop for longo — antes do adiamento. Mova todo o trabalho pesado para depois do adiamento.

Múltiplos modais abertos ao mesmo tempo

O Discord permite apenas um modal aberto por usuário por cliente. Se um usuário abrir um segundo modal enquanto o primeiro ainda está ativo, o primeiro modal é descartado e sua interação é invalidada. O bot pode receber um envio para o segundo modal, mas o primeiro é perdido. Eduque os usuários a enviar um modal de cada vez, ou implemente um cooldown que impeça a abertura de um novo modal até que o anterior seja resolvido.

Métodos de reconhecimento de interação do Discord: Defer vs Reply vs Follow-Up

Método DeferReply Reply
Propósito Reconhecer interação sem enviar resposta imediatamente Reconhecer interação e enviar resposta em uma chamada
Limite de tempo 3 segundos para chamar; 15 minutos para follow-up 3 segundos para concluir toda a chamada
Tipo de resposta Deve usar followUp() ou editReply() após adiar Resposta enviada imediatamente; nenhum follow-up necessário
Caso de uso Consultas longas ao banco de dados, uploads de arquivos, chamadas de API externas Respostas instantâneas como confirmações simples ou erros

Os envios de modal do Discord falham com um timeout de interação de 3 segundos porque o bot não reconhece a interação dentro da janela exigida. Ao chamar interaction.deferReply() ou interaction.deferUpdate() como a primeira ação no seu manipulador de modal, você estende a janela de resposta para 15 minutos. Após o processamento, use interaction.followUp() para enviar o resultado. Para maior confiabilidade, envolva seu manipulador em um try-catch e forneça uma mensagem de fallback se a lógica principal falhar. Teste seu bot com uma simulação de rede lenta para confirmar que o adiamento funciona antes de qualquer operação bloqueante.

ADVERTISEMENT