chenhg5/cc-connect · error
discord: send button followup: %w
Error message
discord: send button followup: %w
What it means
For interaction reply contexts, SendWithButtons first sends the interaction response, then posts the button message as a followup via FollowupMessageCreate; this error wraps any failure of that followup webhook call. The initial interaction reply succeeded, but the followup (which carries the buttons) failed. Root cause lives in the wrapped discordgo error.
Source
Thrown at platform/discord/discord.go:1197
if len(buttons) == 0 {
return fmt.Errorf("discord: no buttons provided")
}
components := buildDiscordActionRows(buttons)
if len(components) == 0 {
return fmt.Errorf("discord: no buttons provided")
}
switch rc := rctx.(type) {
case *interactionReplyCtx:
if err := p.sendInteraction(rc, content); err != nil {
return err
}
_, err := p.session.FollowupMessageCreate(rc.interaction, true, &discordgo.WebhookParams{
Content: content,
Components: components,
})
if err != nil {
return fmt.Errorf("discord: send button followup: %w", err)
}
return nil
case replyContext:
_, err := p.session.ChannelMessageSendComplex(rc.targetChannelID(), &discordgo.MessageSend{
Content: content,
Components: components,
})
if err != nil {
return fmt.Errorf("discord: send channel buttons: %w", err)
}
return nil
default:
return core.ErrNotSupported
}
}
func (p *progressPlatform) ProgressUpdateInterval() time.Duration {
return 2 * time.SecondView on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped error: 404 unknown webhook means the interaction token expired — re-send as a normal channel message instead
- Send the followup promptly after replying to the interaction, well within 15 minutes
- Fall back to ChannelMessageSendComplex with components when the followup fails
- Verify bot SEND_MESSAGES/VIEW_CHANNEL permissions in the target channel
Example fix
// before
_, err := p.session.FollowupMessageCreate(rc.interaction, true, params)
// after
_, err := p.session.FollowupMessageCreate(rc.interaction, true, params)
if err != nil {
_, err = p.session.ChannelMessageSendComplex(rc.channelID, &discordgo.MessageSend{Content: content, Components: components})
} Defensive patterns
Strategy: try-catch
Validate before calling
if time.Since(rc.interactionCreatedAt) > 14*time.Minute {
return errors.New("interaction token near expiry; use channel send instead")
} Try / catch
err := p.SendWithButtons(ctx, rctx, content, buttons)
if err != nil {
var restErr *discordgo.RESTError
if errors.As(err, &restErr) && restErr.Message.Code == 10060 /* unknown webhook */ {
// interaction token expired: fall back to channel message
return sendChannelFallback(ctx, content, buttons)
}
return err
} Prevention
- Send followups promptly, well within the 15-minute interaction-token window
- Implement a channel-message fallback for expired interaction tokens
- Monitor 404 unknown-webhook errors as a token-expiry signal
- Verify channel permissions for the bot in advance
When it happens
Trigger: Interaction token expired (webhook tokens are valid 15 minutes after the interaction) or was already consumed; the bot lacks permission in the channel; Discord API returned 4xx/5xx to the webhook endpoint.
Common situations: Long-running agent work delayed the followup past the 15-minute interaction-token lifetime; bot kicked from channel between replies; transient network/API outage mid-conversation.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- resolve channel %s: %w
- discord: send fallback: %w
- discord: send: %w
- discord: send image fallback: %w
- discord: send image: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/d297d56bfa2f8cd7.
Report an issue: GitHub.