Reply failing on button interaction, getting no errors

Just not sure what I did wrong here. Looks fine according to the discord API guide as far as I can tell. When I hit the yes button, I get an error in discord that says "This interaction failed."
13 Replies
d.js toolkit
d.js toolkit13mo ago
• What's your exact discord.js npm list discord.js and node node -v version? • Post the full error stack trace, not just the top part! • Show your code! • Explain what exactly your issue is. • Not a discord.js issue? Check out #useful-servers.
Squid
Squid13mo ago
How are you acknowledging the button interaction that you get from clicking "Yes"?
Collywog
Collywog13mo ago
//tell the slash command to do things
async execute(interaction, client) {
//create an embed with a title, description, user avatar, timestamp, and 2 fields.
const quizEmbed = new EmbedBuilder()
.setTitle(`Are you ready to begin?`)
.setDescription(`Find out where you stand in the world of gaming.`)
.setColor(0x18e1ee)
.setThumbnail(interaction.user.displayAvatarURL())
.setTimestamp(Date.now())
.addFields([
{
name: ` `,
value: ` `,
inline: true,
},
{
name: ` `,
value: ` `,
inline: true,
},
]);

//create 2 buttons for yes and no on the initial reply
const answer1 = new ButtonBuilder()
.setCustomId("answer1")
.setLabel("Yes")
.setStyle(ButtonStyle.Success);

const answer2 = new ButtonBuilder()
.setCustomId("answer2")
.setLabel("No")
.setStyle(ButtonStyle.Danger);

//Put the buttons on an action row
const row = new ActionRowBuilder().addComponents(answer1, answer2);

//Post the initial reply with the embed and the action row.
//Store the response as a variable
// Make it visible to the user only
const response = await interaction.reply({
embeds: [quizEmbed],
components: [row],
ephemeral: true,
});

//Filter interactions to only the user that created the embed
const collectorFilter = (i) => i.user.id === interaction.user.id;

//wait for an interaction and set a timeout period of 30 minutes
try {
const confirmation = await response.awaitMessageComponent({
filter: collectorFilter,
time: 1800000,
});
//tell the slash command to do things
async execute(interaction, client) {
//create an embed with a title, description, user avatar, timestamp, and 2 fields.
const quizEmbed = new EmbedBuilder()
.setTitle(`Are you ready to begin?`)
.setDescription(`Find out where you stand in the world of gaming.`)
.setColor(0x18e1ee)
.setThumbnail(interaction.user.displayAvatarURL())
.setTimestamp(Date.now())
.addFields([
{
name: ` `,
value: ` `,
inline: true,
},
{
name: ` `,
value: ` `,
inline: true,
},
]);

//create 2 buttons for yes and no on the initial reply
const answer1 = new ButtonBuilder()
.setCustomId("answer1")
.setLabel("Yes")
.setStyle(ButtonStyle.Success);

const answer2 = new ButtonBuilder()
.setCustomId("answer2")
.setLabel("No")
.setStyle(ButtonStyle.Danger);

//Put the buttons on an action row
const row = new ActionRowBuilder().addComponents(answer1, answer2);

//Post the initial reply with the embed and the action row.
//Store the response as a variable
// Make it visible to the user only
const response = await interaction.reply({
embeds: [quizEmbed],
components: [row],
ephemeral: true,
});

//Filter interactions to only the user that created the embed
const collectorFilter = (i) => i.user.id === interaction.user.id;

//wait for an interaction and set a timeout period of 30 minutes
try {
const confirmation = await response.awaitMessageComponent({
filter: collectorFilter,
time: 1800000,
});
if (confirmation.customId === "answer1") {
for (i = 0; i < questions.length; i++) {
await interaction.editReply({
content: "Question" + questions[i].questionNumber,
embeds: [quizEmbed]
.setTitle(questions.questionText)
.setDescription("")
.setFields([
{
name: `Option 1`,
value: questions[i].answer1,
inline: true,
},
{
name: `Answer 2`,
value: questions[i].answer2,
inline: true,
},
]),
});
}
} else if (confirmation.customId === "answer2") {
await confirmation.update({
content: "Action cancelled",
components: [],
});
}
} catch (e) {
await interaction.editReply({
content: "Answer not received within 30 minutes, cancelling",
embeds: [quizEmbed]
.setName(),
components: [],
});
}
if (confirmation.customId === "answer1") {
for (i = 0; i < questions.length; i++) {
await interaction.editReply({
content: "Question" + questions[i].questionNumber,
embeds: [quizEmbed]
.setTitle(questions.questionText)
.setDescription("")
.setFields([
{
name: `Option 1`,
value: questions[i].answer1,
inline: true,
},
{
name: `Answer 2`,
value: questions[i].answer2,
inline: true,
},
]),
});
}
} else if (confirmation.customId === "answer2") {
await confirmation.update({
content: "Action cancelled",
components: [],
});
}
} catch (e) {
await interaction.editReply({
content: "Answer not received within 30 minutes, cancelling",
embeds: [quizEmbed]
.setName(),
components: [],
});
}
that would be in a response const response = interaction.reply()
Squid
Squid13mo ago
That's how you acknowledge the command interaction, but you still need to acknowledge the button interaction confirmation You're doing it correctly for when the custom id is "answer2" but you're not for "answer1"
Collywog
Collywog13mo ago
oh so I would need another confirmation.update before the interaction.reply? so I'm still confused, sorry! I tried a few different things and this is where I'm currently at, but I'm still getting a failure. Am I doing the update wrong?
if (confirmation.customId === "answer1") {
console.log("the yes button was clicked");
for (i = 0; i < questions.length; i++) {
console.log("We're in the loop.")
const answerResponse = await confirmation.update.editReply({
content: "Question" + questions[i].questionNumber,
embeds: [quizEmbed]
.setTitle(questions.questionText)
.setDescription("")
.setFields([
{
name: `Option 1`,
value: questions[i].answer1,
inline: true,
},
{
name: `Answer 2`,
value: questions[i].answer2,
inline: true,
},
]),
});
if (confirmation.customId === "answer1") {
console.log("the yes button was clicked");
for (i = 0; i < questions.length; i++) {
console.log("We're in the loop.")
const answerResponse = await confirmation.update.editReply({
content: "Question" + questions[i].questionNumber,
embeds: [quizEmbed]
.setTitle(questions.questionText)
.setDescription("")
.setFields([
{
name: `Option 1`,
value: questions[i].answer1,
inline: true,
},
{
name: `Answer 2`,
value: questions[i].answer2,
inline: true,
},
]),
});
await confirmation.update({}) didn't work either.
Squid
Squid13mo ago
confirmation.update({}) should've worked Did it throw an error? And if it didn't, did "We're in the loop." get logged?
Collywog
Collywog13mo ago
it threw the same error but We're in the loop. didn't get logged
Squid
Squid13mo ago
That makes it sound like questions is an empty array, so I would recommend logging it to make sure it's populated Also, you can only update() an interaction once; you can't update it multiple times with each question
Collywog
Collywog13mo ago
oh. is there a way I could update it for each question? I want it all to be in the same ephemeral to not cloud the chat
Squid
Squid13mo ago
If you could update it multiple times, think about it: It would update with the first question, then immediately it would replace itself with the second question How do you want to handle showing each of them? For example, you could make it so a prompt has to occur after the first question, then it shows the second question Or, you could send multiple embeds in one message, each containing one question's data You have lots of choices but you need to make sure you know what you're trying to end up with
Collywog
Collywog13mo ago
I was hoping to have each question update the embed with editReply, that way it all happens on one messgae is that possible? is there not a way to nest waiting for a user's input inside an interaction?
Squid
Squid13mo ago
If you're waiting for a user's embed between loops, you can use awaitMessages() or awaitModalSubmit() to collect that input after updating/editing each embed And yes, you can use update() on the first loop (when i === 0) and editReply() on every other loop (when i > 0) and it should work fine
Collywog
Collywog13mo ago
thank you so much! I really appreciate the advice!