Unique Id on modal crashing bot submission after cancel

I see this question all over the discord and I've tried numerous different suggestions that people have given and yet I still can't get this to work. I'm hitting the good ole, "modal pop-up, user hits cancel, modal pop-up again, submit, modal submission is recorded, bot fails due to an unknown interaction 10062. To my knowledge what's happening is there is no response to the first initial opening of the modal. Therefore, when the next modal is completed, the queue is ruined and the bot doesn't know what to do with it. The biggest thing is ensuring that the id of the interation is unique, aka using the interaction.id and setting that to the modal customId, yet this doesn't seem to work for me. I'm even passing in a random number. I'm sure it's something little and if it is, drop me the documentation and tell me it's a skill issue and I'll read more.
const { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, SlashCommandBuilder } = require('discord.js');
let randomNumber = Math.floor(Math.random() * 10000);

module.exports = {
data: new SlashCommandBuilder()
.setName('record')
.setDescription('Records game details.'),
category: 'mtg',
async execute(interaction) {
const modal = new ModalBuilder({
customId: `myModal-${interaction.user.id}-${randomNumber}`,
title: 'Game Summary',
});

// question 1
const whoPlayedInTheGameInput = new TextInputBuilder({
customId: 'whoPlayedInTheGameInput',
label: 'Who played in the game?',
style: TextInputStyle.Short,
});

// question 2
const gameFormatInput = new TextInputBuilder({
customId: 'gameFormatInput',
label: 'What was the game format?',
style: TextInputStyle.Short,
});

...

...

// set rows for the modal
const firstActionRow = new ActionRowBuilder().addComponents(whoPlayedInTheGameInput);
const secondActionRow = new ActionRowBuilder().addComponents(gameFormatInput);
const thirdActionRow = new ActionRowBuilder().addComponents(whoWonTheGameInput);
const fourthActionRow = new ActionRowBuilder().addComponents(howLongWasTheGameInput);
const fifthActionRow = new ActionRowBuilder().addComponents(matchHighlightInput);

modal.addComponents(firstActionRow, secondActionRow, thirdActionRow, fourthActionRow, fifthActionRow);

await interaction.showModal(modal);

// wait for the modal to be submitted
const filter = (interaction) => interaction.customId === `myModal-${interaction.user.id}-${randomNumber}`;

interaction
.awaitModalSubmit({ filter, time: 60_000 })
.then((modalInteraction) => {
const whoPlayedInTheGameInputValue = modalInteraction.fields.getTextInputValue('whoPlayedInTheGameInput');
const gameFormatInputValue = modalInteraction.fields.getTextInputValue('gameFormatInput');
const whoWonTheGameInputValue = modalInteraction.fields.getTextInputValue('whoWonTheGameInput');
const howLongWasTheGameInputValue = modalInteraction.fields.getTextInputValue('howLongWasTheGameInput');
const matchHighlightInputValue = modalInteraction.fields.getTextInputValue('matchHighlightInput');

const output = `Players: ${whoPlayedInTheGameInputValue}\nFormat: ${gameFormatInputValue}\nWinner: ${whoWonTheGameInputValue}\nMatch Time: ${howLongWasTheGameInputValue}\nMatch Highlight: ${matchHighlightInputValue}`;

modalInteraction.reply(output);
console.log(`----- ${interaction.user.username} successfully created a record -----\n${output}`);
})
.catch((err) => {
console.log(`Error: ${err}`);
});
},
};
const { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, SlashCommandBuilder } = require('discord.js');
let randomNumber = Math.floor(Math.random() * 10000);

module.exports = {
data: new SlashCommandBuilder()
.setName('record')
.setDescription('Records game details.'),
category: 'mtg',
async execute(interaction) {
const modal = new ModalBuilder({
customId: `myModal-${interaction.user.id}-${randomNumber}`,
title: 'Game Summary',
});

// question 1
const whoPlayedInTheGameInput = new TextInputBuilder({
customId: 'whoPlayedInTheGameInput',
label: 'Who played in the game?',
style: TextInputStyle.Short,
});

// question 2
const gameFormatInput = new TextInputBuilder({
customId: 'gameFormatInput',
label: 'What was the game format?',
style: TextInputStyle.Short,
});

...

...

// set rows for the modal
const firstActionRow = new ActionRowBuilder().addComponents(whoPlayedInTheGameInput);
const secondActionRow = new ActionRowBuilder().addComponents(gameFormatInput);
const thirdActionRow = new ActionRowBuilder().addComponents(whoWonTheGameInput);
const fourthActionRow = new ActionRowBuilder().addComponents(howLongWasTheGameInput);
const fifthActionRow = new ActionRowBuilder().addComponents(matchHighlightInput);

modal.addComponents(firstActionRow, secondActionRow, thirdActionRow, fourthActionRow, fifthActionRow);

await interaction.showModal(modal);

// wait for the modal to be submitted
const filter = (interaction) => interaction.customId === `myModal-${interaction.user.id}-${randomNumber}`;

interaction
.awaitModalSubmit({ filter, time: 60_000 })
.then((modalInteraction) => {
const whoPlayedInTheGameInputValue = modalInteraction.fields.getTextInputValue('whoPlayedInTheGameInput');
const gameFormatInputValue = modalInteraction.fields.getTextInputValue('gameFormatInput');
const whoWonTheGameInputValue = modalInteraction.fields.getTextInputValue('whoWonTheGameInput');
const howLongWasTheGameInputValue = modalInteraction.fields.getTextInputValue('howLongWasTheGameInput');
const matchHighlightInputValue = modalInteraction.fields.getTextInputValue('matchHighlightInput');

const output = `Players: ${whoPlayedInTheGameInputValue}\nFormat: ${gameFormatInputValue}\nWinner: ${whoWonTheGameInputValue}\nMatch Time: ${howLongWasTheGameInputValue}\nMatch Highlight: ${matchHighlightInputValue}`;

modalInteraction.reply(output);
console.log(`----- ${interaction.user.username} successfully created a record -----\n${output}`);
})
.catch((err) => {
console.log(`Error: ${err}`);
});
},
};
9 Replies
d.js toolkit
d.js toolkit4mo 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 staff
duck
duck4mo ago
you're adding the user's id to the custom id which won't be unique per interaction because it's still the same user in this scenario and your random number appears to be generated once upon loading the file, not every time you receive this command
Gbrad
Gbrad4mo ago
Okay so I tried this and it still doesn’t work. I changed the custom id to ‘my-modal-${interaction.Id}’
duck
duck4mo ago
in what way does it not work? care to share your updated code?
Gbrad
Gbrad4mo ago
Yes one moment please new code
const { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('record')
.setDescription('Records game details.'),
category: 'mtg',
async execute(interaction) {
const modal = new ModalBuilder({
customId: `myModal-${interaction.id}`,
title: 'Game Summary',
});

// question 1
const whoPlayedInTheGameInput = new TextInputBuilder({
customId: 'whoPlayedInTheGameInput',
label: 'Who played in the game?',
style: TextInputStyle.Short,
});

...

// set rows for the modal
const firstActionRow = new ActionRowBuilder().addComponents(whoPlayedInTheGameInput);
const secondActionRow = new ActionRowBuilder().addComponents(gameFormatInput);
const thirdActionRow = new ActionRowBuilder().addComponents(whoWonTheGameInput);
const fourthActionRow = new ActionRowBuilder().addComponents(howLongWasTheGameInput);
const fifthActionRow = new ActionRowBuilder().addComponents(matchHighlightInput);

modal.addComponents(firstActionRow, secondActionRow, thirdActionRow, fourthActionRow, fifthActionRow);

await interaction.showModal(modal);

// wait for the modal to be submitted
const filter = (interaction) => interaction.customId === `myModal-${interaction.id}`;

interaction
.awaitModalSubmit({ filter, time: 60_000 })
.then((modalInteraction) => {
const whoPlayedInTheGameInputValue = modalInteraction.fields.getTextInputValue('whoPlayedInTheGameInput');
const gameFormatInputValue = modalInteraction.fields.getTextInputValue('gameFormatInput');
const whoWonTheGameInputValue = modalInteraction.fields.getTextInputValue('whoWonTheGameInput');
const howLongWasTheGameInputValue = modalInteraction.fields.getTextInputValue('howLongWasTheGameInput');
const matchHighlightInputValue = modalInteraction.fields.getTextInputValue('matchHighlightInput');

const output = `Players: ${whoPlayedInTheGameInputValue}\nFormat: ${gameFormatInputValue}\nWinner: ${whoWonTheGameInputValue}\nMatch Time: ${howLongWasTheGameInputValue}\nMatch Highlight: ${matchHighlightInputValue}`;

modalInteraction.reply(output);
console.log(`----- ${interaction.user.username} successfully created a record -----\n${output}`);
})
.catch((err) => {
console.log(`Error: ${err}`);
});
},
};
const { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('record')
.setDescription('Records game details.'),
category: 'mtg',
async execute(interaction) {
const modal = new ModalBuilder({
customId: `myModal-${interaction.id}`,
title: 'Game Summary',
});

// question 1
const whoPlayedInTheGameInput = new TextInputBuilder({
customId: 'whoPlayedInTheGameInput',
label: 'Who played in the game?',
style: TextInputStyle.Short,
});

...

// set rows for the modal
const firstActionRow = new ActionRowBuilder().addComponents(whoPlayedInTheGameInput);
const secondActionRow = new ActionRowBuilder().addComponents(gameFormatInput);
const thirdActionRow = new ActionRowBuilder().addComponents(whoWonTheGameInput);
const fourthActionRow = new ActionRowBuilder().addComponents(howLongWasTheGameInput);
const fifthActionRow = new ActionRowBuilder().addComponents(matchHighlightInput);

modal.addComponents(firstActionRow, secondActionRow, thirdActionRow, fourthActionRow, fifthActionRow);

await interaction.showModal(modal);

// wait for the modal to be submitted
const filter = (interaction) => interaction.customId === `myModal-${interaction.id}`;

interaction
.awaitModalSubmit({ filter, time: 60_000 })
.then((modalInteraction) => {
const whoPlayedInTheGameInputValue = modalInteraction.fields.getTextInputValue('whoPlayedInTheGameInput');
const gameFormatInputValue = modalInteraction.fields.getTextInputValue('gameFormatInput');
const whoWonTheGameInputValue = modalInteraction.fields.getTextInputValue('whoWonTheGameInput');
const howLongWasTheGameInputValue = modalInteraction.fields.getTextInputValue('howLongWasTheGameInput');
const matchHighlightInputValue = modalInteraction.fields.getTextInputValue('matchHighlightInput');

const output = `Players: ${whoPlayedInTheGameInputValue}\nFormat: ${gameFormatInputValue}\nWinner: ${whoWonTheGameInputValue}\nMatch Time: ${howLongWasTheGameInputValue}\nMatch Highlight: ${matchHighlightInputValue}`;

modalInteraction.reply(output);
console.log(`----- ${interaction.user.username} successfully created a record -----\n${output}`);
})
.catch((err) => {
console.log(`Error: ${err}`);
});
},
};
New issue when I try this though. The modal won't submit.
duck
duck4mo ago
(interaction) => interaction.customId === `myModal-${interaction.id}`
(interaction) => interaction.customId === `myModal-${interaction.id}`
you may want to rethink which interaction's id you want to access here
Gbrad
Gbrad4mo ago
hmmmm does that not look at the current interaction?
duck
duck4mo ago
(you could probably start by not naming multiple variables the same thing)
Gbrad
Gbrad4mo ago
let me mess around with it a bit Okay I owe you a thank you. This was a skill issue. I'm new to JS so I was being a bonehead and just trying to use arrow syntax functions without truly knowing what they do. Here are my changes
modal.addComponents(firstActionRow, secondActionRow, thirdActionRow, fourthActionRow, fifthActionRow);

await interaction.showModal(modal);

// wait for the modal to be submitted
const filter = (currentInteraction) => currentInteraction.customId === `myModal-${interaction.id}`;

interaction
.awaitModalSubmit({ filter, time: 60_000 })
.then((modalInteraction) => {
const whoPlayedInTheGameInputValue = modalInteraction.fields.getTextInputValue('whoPlayedInTheGameInput');
const gameFormatInputValue = modalInteraction.fields.getTextInputValue('gameFormatInput');
const whoWonTheGameInputValue = modalInteraction.fields.getTextInputValue('whoWonTheGameInput');
const howLongWasTheGameInputValue = modalInteraction.fields.getTextInputValue('howLongWasTheGameInput');
const matchHighlightInputValue = modalInteraction.fields.getTextInputValue('matchHighlightInput');

const output = `Players: ${whoPlayedInTheGameInputValue}\nFormat: ${gameFormatInputValue}\nWinner: ${whoWonTheGameInputValue}\nMatch Time: ${howLongWasTheGameInputValue}\nMatch Highlight: ${matchHighlightInputValue}`;

modalInteraction.reply(output);
console.log(`----- ${interaction.user.username} successfully created a record -----\n${output}`);
})
.catch((err) => {
console.log(`Error: ${err}`);
});
},
modal.addComponents(firstActionRow, secondActionRow, thirdActionRow, fourthActionRow, fifthActionRow);

await interaction.showModal(modal);

// wait for the modal to be submitted
const filter = (currentInteraction) => currentInteraction.customId === `myModal-${interaction.id}`;

interaction
.awaitModalSubmit({ filter, time: 60_000 })
.then((modalInteraction) => {
const whoPlayedInTheGameInputValue = modalInteraction.fields.getTextInputValue('whoPlayedInTheGameInput');
const gameFormatInputValue = modalInteraction.fields.getTextInputValue('gameFormatInput');
const whoWonTheGameInputValue = modalInteraction.fields.getTextInputValue('whoWonTheGameInput');
const howLongWasTheGameInputValue = modalInteraction.fields.getTextInputValue('howLongWasTheGameInput');
const matchHighlightInputValue = modalInteraction.fields.getTextInputValue('matchHighlightInput');

const output = `Players: ${whoPlayedInTheGameInputValue}\nFormat: ${gameFormatInputValue}\nWinner: ${whoWonTheGameInputValue}\nMatch Time: ${howLongWasTheGameInputValue}\nMatch Highlight: ${matchHighlightInputValue}`;

modalInteraction.reply(output);
console.log(`----- ${interaction.user.username} successfully created a record -----\n${output}`);
})
.catch((err) => {
console.log(`Error: ${err}`);
});
},
The fix was that the const filter is a function and then (currentInteraction) is an inline function itself that takes in one parameter and this is declared as currentInteraction. Now the method looks at the parameter's customId and checks it against the id set at the top of the class. Constructive criticism is my favorite so thank you @duck for making me rethink my work.