Responses and deferral
Return a value, defer slow interactions, or reply yourself.
The easy path is to return something from the callback. SWAGcommands accepts a string, a discord.js MessagePayload, or the options object supported by the Discord response method for that invocation.
callback: async () => ({
content: "Here's the result",
embeds: [embed],
components: [row],
})| Invocation | What SWAGcommands calls |
|---|---|
| Fresh slash or context-menu interaction | interaction.reply(result) |
| Deferred interaction | interaction.editReply(result) |
Message command with reply: true | message.reply(result) |
| Other message command | message.channel.send(result) |
undefined means “I handled this myself” or “send nothing.” The framework checks specifically for undefined, so an empty string is still handed to Discord and may be rejected there.
Slow work: defer first
const report = {
type: CommandType.SLASH,
description: "Generate a report",
deferReply: { ephemeral: true },
callback: async () => {
const result = await makeReport();
return { content: result };
},
} satisfies CommandObject;deferReply: true acknowledges an interaction before the callback and later edits that reply. The object form with ephemeral: true makes the deferred reply private. For message commands, deferReply sends a typing indicator instead. A subcommand leaf can override its root's setting.
If your callback calls interaction.reply() directly, return undefined to avoid a second response. Duplicate acknowledgements, failed sends, and callback failures are reported through structured errors. onError lets you log or handle them centrally.