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

  1. 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
  2. Re-invite the bot with correct permissions or fix role/channel overrides in Discord Server Settings
  3. Check Discord status / retry — if both endpoints failed transiently the next message will likely succeed
  4. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/c4b173b4a969d7ff. Report an issue: GitHub.