discordjs/discord.js · error · DiscordjsError
InteractionAlreadyReplied
InteractionAlreadyReplied
Error message
The reply to this interaction has already been sent or deferred.
What it means
Interaction reply state guard: an interaction can only have one initial response. deferReply throws InteractionAlreadyReplied when this.deferred or this.replied is already true, because Discord rejects a second initial callback (interaction has already been acknowledged).
Source
Thrown at packages/discord.js/src/structures/interfaces/InteractionResponses.js:83
/**
* Defers the reply to this interaction.
*
* @param {InteractionDeferReplyOptions} [options] Options for deferring the reply to this interaction
* @returns {Promise<InteractionCallbackResponse|undefined>}
* @example
* // Defer the reply to this interaction
* interaction.deferReply()
* .then(console.log)
* .catch(console.error)
* @example
* // Defer to send an ephemeral reply later
* interaction.deferReply({ flags: MessageFlags.Ephemeral })
* .then(console.log)
* .catch(console.error);
*/
async deferReply(options = {}) {
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
const resolvedFlags = new MessageFlagsBitField(options.flags);
const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
body: {
type: InteractionResponseType.DeferredChannelMessageWithSource,
data: {
flags: resolvedFlags.bitfield,
},
},
auth: false,
query: makeURLSearchParams({ with_response: options.withResponse ?? false }),
});
this.deferred = true;
this.ephemeral = resolvedFlags.has(MessageFlags.Ephemeral);
return options.withResponse ? new InteractionCallbackResponse(this.client, response) : undefined;View on GitHub (pinned to a81ed8a306)
Solutions
- Check interaction.deferred / interaction.replied before deferring and only defer when neither is set.
- If already deferred, send content with interaction.editReply() instead of deferring again.
- If already replied, use interaction.followUp() for additional messages.
- Ensure your interaction handler is registered once (guard duplicate client event listeners).
Example fix
// before
await interaction.deferReply();
await interaction.deferReply({ ephemeral: true }); // throws
// after
if (!interaction.deferred && !interaction.replied) {
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
} else {
await interaction.editReply({ content: 'Working...' });
} Defensive patterns
Strategy: try-catch
Validate before calling
const canDefer = !interaction.deferred && !interaction.replied;
Try / catch
try {
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
} catch (err) {
if (err?.code === 'InteractionAlreadyReplied') {
await interaction.editReply({ content: 'Working...' }).catch(() => {});
} else throw err;
} Prevention
- Acknowledge each interaction exactly once, in one designated place.
- Check deferred/replied flags before any ack call.
- Register interaction handlers only once (guard duplicate listeners).
- Use editReply/followUp for everything after the initial ack.
When it happens
Trigger: Calling interaction.deferReply() after already calling reply(), deferReply(), deferUpdate(), update(), or launchActivity() on the same interaction instance — including following a defer that later auto-set replied via followUp.
Common situations: Handler runs twice due to duplicate event registration or component-collector rebinding; a code path that defers at the top and the caller defers again in an error branch; switching from reply to deferReply during refactor without removing the earlier ack.
Related errors
- InteractionNotReplied
- Request timed out
- HTTPError(status, res.statusText, method, url, requestData)
- Session not available
- Not enough sessions remaining to spawn ${shardIds.length} sh
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/e8be483159458f9a.
Report an issue: GitHub.