chenhg5/cc-connect · error

discord: send file fallback: %w

Error message

discord: send file fallback: %w

What it means

SendFile failed to deliver a file attachment through the Discord interaction webhook AND the fallback ChannelMessageSendComplex upload in the originating channel also failed. Both delivery paths returned errors from the Discord API (or transport), so the attachment was never delivered. The wrapped error is from the fallback multipart upload.

Source

Thrown at platform/discord/discord.go:1133

		rc.mu.Unlock()

		var err error
		if first {
			_, err = p.session.InteractionResponseEdit(rc.interaction, &discordgo.WebhookEdit{
				Files: []*discordgo.File{newFile()},
			})
		} else {
			_, err = p.session.FollowupMessageCreate(rc.interaction, true, &discordgo.WebhookParams{
				Files: []*discordgo.File{newFile()},
			})
		}
		if err != nil {
			slog.Warn("discord: interaction file failed, falling back to channel message", "error", err)
			_, err = p.session.ChannelMessageSendComplex(rc.channelID, &discordgo.MessageSend{
				Files: []*discordgo.File{newFile()},
			})
			if err != nil {
				return fmt.Errorf("discord: send file fallback: %w", err)
			}
		}
		return nil
	case replyContext:
		_, err := p.session.ChannelMessageSendComplex(rc.targetChannelID(), &discordgo.MessageSend{
			Files: []*discordgo.File{newFile()},
		})
		if err != nil {
			return fmt.Errorf("discord: send file: %w", err)
		}
		return nil
	default:
		return fmt.Errorf("discord: SendFile: invalid reply context type %T", rctx)
	}
}

func buildDiscordActionRows(rows [][]core.ButtonOption) []discordgo.MessageComponent {
	components := make([]discordgo.MessageComponent, 0, len(rows))

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the wrapped error code: 403 → grant Send Messages + Attach Files to the bot role in that channel; size errors → reduce file size or compress
  2. Verify the channel (rc.channelID) still exists and the bot is still in the guild
  3. Check file.MimeType and FileName are valid and match the payload
  4. If files are consistently too large, host externally and send a link instead of an attachment
Defensive patterns

Strategy: fallback

Validate before calling

const maxUpload = 8 << 20
if len(file.Data) > maxUpload {
    return fmt.Errorf("file %s (%d bytes) exceeds discord upload limit", file.FileName, len(file.Data))
}

Try / catch

var apiErr *discordgo.RESTError
if errors.As(err, &apiErr) {
    switch apiErr.Message.Code {
    case 50013: // missing permissions
        slog.Error("discord: bot cannot attach files in channel", "channel", rc.channelID)
    case 40005: // request entity too large
        slog.Error("discord: file too large for upload", "file", file.FileName)
    }
}

Prevention

When it happens

Trigger: Interaction expired/invalid plus fallback failure: 403 Missing Permissions or Missing Attach Files, deleted channel, file exceeding the guild upload size limit, or network/proxy failure during upload.

Common situations: Sending large generated files (build artifacts, diffs) over Discord's upload cap; bot permissions revoked mid-conversation; session outliving the interaction's 15-minute window while the channel also became inaccessible.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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