chenhg5/cc-connect · error
discord: send fallback: %w
Error message
discord: send fallback: %w
What it means
When responding via the Discord interaction webhook fails, sendInteraction automatically falls back to a plain ChannelMessageSend in the originating channel. This error is thrown only when that fallback ALSO fails, meaning both the interaction response path and the direct channel-send path were rejected. The wrapped error comes from the discordgo ChannelMessageSend call, e.g. HTTP 403 Missing Permissions or 404 Unknown Channel.
Source
Thrown at platform/discord/discord.go:1001
first := !ictx.firstDone
if first {
ictx.firstDone = true
}
ictx.mu.Unlock()
var err error
if first {
c := chunk
_, err = p.session.InteractionResponseEdit(ictx.interaction, &discordgo.WebhookEdit{Content: &c})
} else {
_, err = p.session.FollowupMessageCreate(ictx.interaction, true, &discordgo.WebhookParams{Content: chunk})
}
if err != nil {
slog.Warn("discord: interaction response failed, falling back to channel message", "error", err)
_, err = p.session.ChannelMessageSend(ictx.channelID, chunk)
if err != nil {
return fmt.Errorf("discord: send fallback: %w", err)
}
}
}
return nil
}
func (p *Platform) sendChannelReply(rc replyContext, content string) error {
chunks := core.SplitMessageCodeFenceAware(wrapTablesInCodeBlocks(content), maxDiscordLen)
for _, chunk := range chunks {
var err error
if rc.useThreadChannel() || rc.messageID == "" {
_, err = p.session.ChannelMessageSend(rc.targetChannelID(), chunk)
} else {
ref := &discordgo.MessageReference{MessageID: rc.messageID}
_, err = p.session.ChannelMessageSendReply(rc.channelID, chunk, ref)
}
if err != nil {
return fmt.Errorf("discord: send: %w", err)View on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped discordgo error's HTTP code: 403 → grant the bot Send Messages/View Channel permission in that channel; 404 → verify the channel still exists
- Re-invite the bot with correct permissions or fix role/channel overrides in Discord Server Settings
- Check Discord status / retry — if both endpoints failed transiently the next message will likely succeed
- Log ictx.channelID and confirm the bot can see that channel (bot must be a member of the guild)
Defensive patterns
Strategy: retry
Validate before calling
// before replying, confirm the bot can post to the channel
hasPerm, _ := p.session.State.UserChannelPermissions(p.botID, ictx.channelID)
if hasPerm&discordgo.PermissionSendMessages == 0 {
return fmt.Errorf("bot lacks Send Messages permission in %s", ictx.channelID)
} Try / catch
var apiErr *discordgo.RESTError
if errors.As(err, &apiErr) {
switch apiErr.Message.Code {
case 50001, 50013: // missing access / missing permissions
// alert admin to fix bot role permissions
}
} Prevention
- Grant the bot Send Messages + View Channel in every channel it serves
- Reply within the 15-minute interaction window when possible
- Alert admins on repeated fallback failures instead of silently dropping messages
- Monitor wrapped discordgo error codes for 403/404
When it happens
Trigger: The deferred interaction has expired (>15 min) or the webhook token is invalid AND the bot lacks Send Messages permission (or the channel was deleted) so the fallback also returns an error.
Common situations: Bot permission was revoked after the interaction started; the user moved/deleted the channel mid-session; Discord API outage affecting both endpoints; replying long after the 15-minute interaction window with the bot not in the channel anymore.
Related errors
- discord: send: %w
- discord: send image fallback: %w
- discord: send image: %w
- discord: send file fallback: %w
- discord: send channel buttons: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/c4b173b4a969d7ff.
Report an issue: GitHub.