Problem
The replyWithResult function in interaction-router.ts uses editReply({ content: '...' }) as a fallback when a spark defers but never replies. This fails when the deferred interaction targets a Components V2 message, because Discord's API rejects content (a legacy field) alongside MessageFlags.IsComponentsV2.
Error: DiscordAPIError[50035]: Invalid Form Body — content[MESSAGE_CANNOT_USE_LEGACY_FIELDS_WITH_COMPONENTS_V2]
Root Cause
When a component handler calls deferUpdate() on a button inside a V2 message:
interaction.deferred becomes true, interaction.replied stays false
- If the handler completes without calling
editReply(), the router's fallback fires
- The fallback calls
editReply({ content: 'Something went wrong...' })
- This attempts to edit the original V2 message with a legacy
content field → API error
Relevant code: interaction-router.ts lines 38–65
Suggested Approach
The router doesn't know whether the deferred interaction targets a V2 message or a legacy one. Options:
- Wrap fallback
editReply in attempt() — prevents the secondary error from propagating, though the user still gets no response
- Send a new ephemeral
followUp instead of editReply — always safe regardless of original message type
- Detect V2 context — check
interaction.message?.flags for IsComponentsV2 and adjust the reply strategy
Option 2 seems simplest and most robust.
Workaround
For now, bot-side handlers should avoid deferUpdate() on V2 component messages without a subsequent editReply(). Use deferReply({ flags: MessageFlags.Ephemeral }) + editReply() instead.
Applied in unbound via fix/close-button-v2-compat.
Problem
The
replyWithResultfunction ininteraction-router.tsuseseditReply({ content: '...' })as a fallback when a spark defers but never replies. This fails when the deferred interaction targets a Components V2 message, because Discord's API rejectscontent(a legacy field) alongsideMessageFlags.IsComponentsV2.Error:
DiscordAPIError[50035]: Invalid Form Body — content[MESSAGE_CANNOT_USE_LEGACY_FIELDS_WITH_COMPONENTS_V2]Root Cause
When a component handler calls
deferUpdate()on a button inside a V2 message:interaction.deferredbecomestrue,interaction.repliedstaysfalseeditReply(), the router's fallback fireseditReply({ content: 'Something went wrong...' })contentfield → API errorRelevant code:
interaction-router.tslines 38–65Suggested Approach
The router doesn't know whether the deferred interaction targets a V2 message or a legacy one. Options:
editReplyinattempt()— prevents the secondary error from propagating, though the user still gets no responsefollowUpinstead ofeditReply— always safe regardless of original message typeinteraction.message?.flagsforIsComponentsV2and adjust the reply strategyOption 2 seems simplest and most robust.
Workaround
For now, bot-side handlers should avoid
deferUpdate()on V2 component messages without a subsequenteditReply(). UsedeferReply({ flags: MessageFlags.Ephemeral })+editReply()instead.Applied in unbound via
fix/close-button-v2-compat.