Can't use modal after button

const { ActionRowBuilder,PermissionFlagsBits,PermissionsBitField, ModalBuilder, TextInputBuilder, TextInputStyle, ButtonBuilder, ButtonStyle, SlashCommandBuilder,EmbedBuilder, } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ticketmessinit')
.setDescription('add')
.setDMPermission(false),
async execute(interaction) {
await interaction.deferReply();
await interaction.deleteReply();
const eventtic = new EmbedBuilder()
···
const create = new ButtonBuilder()
.setCustomId('ticketinit')
.setLabel('Create a ticket')
.setStyle(ButtonStyle.Primary);

const cancel = new ButtonBuilder()
.setCustomId('cancel')
.setLabel('Cancel')
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder()
.addComponents(create,cancel);
const msg = await interaction.channel.send({
embeds:[eventtic],
components: [row],
});
const collector = msg.createMessageComponentCollector();
collector.on('collect',async i =>{
interaction.deferReply();
if (i.customId=='ticketinit'){
// Create the modal
const modal = new ModalBuilder()
.setCustomId('myModal')
.setTitle('My Modal');
// Add components to modal
// Create the text input components
const favoriteColorInput = new TextInputBuilder()
.setCustomId('Eventid')
// The label is the prompt the user sees for this input
.setLabel("What's the ID of your VTC's event?")
// Short means only a single line of text
.setStyle(TextInputStyle.Short);
// An action row only holds one text input,
// so you need one action row per text input.
const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
// Add inputs to the modal
modal.addComponents(firstActionRow);
// Show the modal to the user
await interaction.showModal(modal);
const filter = (o) => o.customId === 'myModal';
interaction.awaitModalSubmit({ time: 50_000, filter })
.then(async(interaction) => {···
if (data.error == false){···
} else {
interaction.channel.send({content:'Can\'t find the event!',ephemeral:true});
}
})
.catch(err => console.log('No modal submit interaction was collected'));
} else if(i.customId=='cancel'){
interaction.update();
}
});
},
};
const { ActionRowBuilder,PermissionFlagsBits,PermissionsBitField, ModalBuilder, TextInputBuilder, TextInputStyle, ButtonBuilder, ButtonStyle, SlashCommandBuilder,EmbedBuilder, } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ticketmessinit')
.setDescription('add')
.setDMPermission(false),
async execute(interaction) {
await interaction.deferReply();
await interaction.deleteReply();
const eventtic = new EmbedBuilder()
···
const create = new ButtonBuilder()
.setCustomId('ticketinit')
.setLabel('Create a ticket')
.setStyle(ButtonStyle.Primary);

const cancel = new ButtonBuilder()
.setCustomId('cancel')
.setLabel('Cancel')
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder()
.addComponents(create,cancel);
const msg = await interaction.channel.send({
embeds:[eventtic],
components: [row],
});
const collector = msg.createMessageComponentCollector();
collector.on('collect',async i =>{
interaction.deferReply();
if (i.customId=='ticketinit'){
// Create the modal
const modal = new ModalBuilder()
.setCustomId('myModal')
.setTitle('My Modal');
// Add components to modal
// Create the text input components
const favoriteColorInput = new TextInputBuilder()
.setCustomId('Eventid')
// The label is the prompt the user sees for this input
.setLabel("What's the ID of your VTC's event?")
// Short means only a single line of text
.setStyle(TextInputStyle.Short);
// An action row only holds one text input,
// so you need one action row per text input.
const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
// Add inputs to the modal
modal.addComponents(firstActionRow);
// Show the modal to the user
await interaction.showModal(modal);
const filter = (o) => o.customId === 'myModal';
interaction.awaitModalSubmit({ time: 50_000, filter })
.then(async(interaction) => {···
if (data.error == false){···
} else {
interaction.channel.send({content:'Can\'t find the event!',ephemeral:true});
}
})
.catch(err => console.log('No modal submit interaction was collected'));
} else if(i.customId=='cancel'){
interaction.update();
}
});
},
};
16 Replies
d.js toolkit
d.js toolkit5mo ago
- What's your exact discord.js npm list discord.js and node node -v version? - Not a discord.js issue? Check out #other-js-ts. - Consider reading #how-to-get-help to improve your question! - Explain what exactly your issue is. - Post the full error stack trace, not just the top part! - Show your code! - Issue solved? Press the button! - Marked as resolved by OP
chewie
chewie5mo ago
You can't show a modal after using deferReply()
Unicorn.
Unicorn.5mo ago
if i use interaciton.update it shows it's not a function if i didn't use deferReply() it will shows replied when i click the button
chewie
chewie5mo ago
why are you not just using interaction.reply() to send the buttons and then i.showModal() in the collector your current approach will not work
Unicorn.
Unicorn.5mo ago
i used as this it shows
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
^
Error [InteractionAlreadyReplied]: The reply to this interaction has already been sent or deferred.
at ChatInputCommandInteraction.showModal (E:\htcqqcom\桌面\bot\marking main\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:255:46)
at InteractionCollector.<anonymous> (E:\htcqqcom\桌面\bot\marking main\commands\slash\ticketmessinit.js:49:29)
at InteractionCollector.emit (node:events:526:35)
at InteractionCollector.handleCollect (E:\htcqqcom\桌面\bot\marking main\node_modules\discord.js\src\structures\interfaces\Collector.js:133:14)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: 'InteractionAlreadyReplied'
}

Node.js v18.17.1
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
^
Error [InteractionAlreadyReplied]: The reply to this interaction has already been sent or deferred.
at ChatInputCommandInteraction.showModal (E:\htcqqcom\桌面\bot\marking main\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:255:46)
at InteractionCollector.<anonymous> (E:\htcqqcom\桌面\bot\marking main\commands\slash\ticketmessinit.js:49:29)
at InteractionCollector.emit (node:events:526:35)
at InteractionCollector.handleCollect (E:\htcqqcom\桌面\bot\marking main\node_modules\discord.js\src\structures\interfaces\Collector.js:133:14)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: 'InteractionAlreadyReplied'
}

Node.js v18.17.1
chewie
chewie5mo ago
Show the new code
d.js docs
d.js docs5mo ago
To share long code snippets, use a service like gist, sourcebin, pastebin, or similar instead of posting them as large code blocks or files.
Unicorn.
Unicorn.5mo ago
const { ActionRowBuilder,PermissionFlagsBits,PermissionsBitField, ModalBuilder, TextInputBuilder, TextInputStyle, ButtonBuilder, ButtonStyle, SlashCommandBuilder,EmbedBuilder, } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ticketmessinit')
.setDescription('add')
.setDMPermission(false),
async execute(interaction) {
await interaction.reply({content:'test' , ephemeral:true});
const eventtic = new EmbedBuilder()
···;
const create = new ButtonBuilder()
.setCustomId('ticketinit')
.setLabel('Create a ticket')
.setStyle(ButtonStyle.Primary);

const cancel = new ButtonBuilder()
.setCustomId('cancel')
.setLabel('Cancel')
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder()
.addComponents(create,cancel);
const msg = await interaction.channel.send({
embeds:[eventtic],
components: [row],
});
const collector = msg.createMessageComponentCollector();
collector.on('collect',async i =>{
if (i.customId=='ticketinit'){
// Create the modal
const modal = new ModalBuilder()
.setCustomId('myModal')
.setTitle('My Modal');
// Add components to modal
// Create the text input components
const favoriteColorInput = new TextInputBuilder()
.setCustomId('Eventid')
// The label is the prompt the user sees for this input
.setLabel("What's the ID of your VTC's event?")
// Short means only a single line of text
.setStyle(TextInputStyle.Short);
// An action row only holds one text input,
// so you need one action row per text input.
const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
// Add inputs to the modal
modal.addComponents(firstActionRow);
// Show the modal to the user
await interaction.showModal(modal);
const filter = (o) => o.customId === 'myModal';
interaction.awaitModalSubmit({ time: 50_000, filter })
.then(async(interaction) => {
···
if (data.error == false){
···
return;
} else {
interaction.channel.send({content:'Can\'t find the event!',ephemeral:true});
}
})
.catch(err => console.log('No modal submit interaction was collected'));
} else if(i.customId=='cancel'){
interaction.channel.send({content:'canceled',ephemeral:true})
}
});
},
};
const { ActionRowBuilder,PermissionFlagsBits,PermissionsBitField, ModalBuilder, TextInputBuilder, TextInputStyle, ButtonBuilder, ButtonStyle, SlashCommandBuilder,EmbedBuilder, } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('ticketmessinit')
.setDescription('add')
.setDMPermission(false),
async execute(interaction) {
await interaction.reply({content:'test' , ephemeral:true});
const eventtic = new EmbedBuilder()
···;
const create = new ButtonBuilder()
.setCustomId('ticketinit')
.setLabel('Create a ticket')
.setStyle(ButtonStyle.Primary);

const cancel = new ButtonBuilder()
.setCustomId('cancel')
.setLabel('Cancel')
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder()
.addComponents(create,cancel);
const msg = await interaction.channel.send({
embeds:[eventtic],
components: [row],
});
const collector = msg.createMessageComponentCollector();
collector.on('collect',async i =>{
if (i.customId=='ticketinit'){
// Create the modal
const modal = new ModalBuilder()
.setCustomId('myModal')
.setTitle('My Modal');
// Add components to modal
// Create the text input components
const favoriteColorInput = new TextInputBuilder()
.setCustomId('Eventid')
// The label is the prompt the user sees for this input
.setLabel("What's the ID of your VTC's event?")
// Short means only a single line of text
.setStyle(TextInputStyle.Short);
// An action row only holds one text input,
// so you need one action row per text input.
const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
// Add inputs to the modal
modal.addComponents(firstActionRow);
// Show the modal to the user
await interaction.showModal(modal);
const filter = (o) => o.customId === 'myModal';
interaction.awaitModalSubmit({ time: 50_000, filter })
.then(async(interaction) => {
···
if (data.error == false){
···
return;
} else {
interaction.channel.send({content:'Can\'t find the event!',ephemeral:true});
}
})
.catch(err => console.log('No modal submit interaction was collected'));
} else if(i.customId=='cancel'){
interaction.channel.send({content:'canceled',ephemeral:true})
}
});
},
};
chewie
chewie5mo ago
i.showModal() not interaction.showModal() Also once again, why are you not sending the buttons in the interaction.reply
Unicorn.
Unicorn.5mo ago
due to i want to let it as all could using interaciton will has a command row
Unicorn.
Unicorn.5mo ago
No description
Unicorn.
Unicorn.5mo ago
i want to let it as this oh i get it if i used interaciton.show Modal it will has the promise of main not the modal
Unicorn.
Unicorn.5mo ago
No description
Unicorn.
Unicorn.5mo ago
it did the work but modal replies error
chewie
chewie5mo ago
then you didn't reply to the modal also you should change the name of your interaction inside awaitModalSubmit
Unicorn.
Unicorn.5mo ago
thx:huge: :huge: :huge: :huge: :huge: :huge: :blobreachReverse: :blobreachReverse: :blobreachReverse: it done
Want results from more Discord servers?
Add your server