chenhg5/cc-connect · error
discord: SendFile: invalid reply context type %T
Error message
discord: SendFile: invalid reply context type %T
What it means
SendFile receives a reply context value whose concrete type is neither *interactionReplyCtx nor replyContext, so the library cannot determine where to send the file. This is a programming/contract error internal to the platform abstraction, not a Discord API failure. The %T verb prints the actual offending type to help locate the mismatch.
Source
Thrown at platform/discord/discord.go:1146
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))
for _, row := range rows {
if len(row) == 0 {
continue
}
buttons := make([]discordgo.MessageComponent, 0, len(row))
for idx, btn := range row {
style := discordgo.SecondaryButton
switch idx {
case 0:
style = discordgo.SuccessButton
case 1:
style = discordgo.DangerButton
case 2:View on GitHub (pinned to 4000b2338a)
Solutions
- Only pass reply contexts created by this Discord platform (replyContext / *interactionReplyCtx)
- Log the %T value shown in the error and trace where the wrong type was created
- If bridging from another platform, convert the context or send via that platform's own adapter
- Add a unit test covering SendFile with the exact context type your code path produces
Example fix
// before: wrong type from another platform
p.SendFile(ctx, someOtherPlatformCtx, path)
// after: use the platform's own reply context
rc, err := p.ReconstructReplyCtx(sessionKey)
if err != nil { return err }
return p.SendFile(ctx, rc, path) Defensive patterns
Strategy: type-guard
Type guard
func isValidDiscordReplyCtx(rctx any) bool {
switch rctx.(type) {
case replyContext, *interactionReplyCtx:
return true
}
return false
} Try / catch
rc, ok := rctx.(replyContext)
if !ok {
return fmt.Errorf("SendFile requires a discord replyContext, got %T", rctx)
}
err := p.SendFile(ctx, rctx, path) Prevention
- Only obtain reply contexts from the same platform instance
- Never pass reply contexts across platform adapters
- Add a type assertion or guard at the call site
- Keep context constructors and consumers in sync during refactors
When it happens
Trigger: Calling Platform.SendFile with a reply context that was constructed manually, came from a different platform, or was zero-valued instead of obtained from the engine/session plumbing.
Common situations: A new custom platform adapter reuses Discord's SendFile with its own context type; refactoring changed the context struct type; passing nil interface instead of a typed context.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- discord: invalid reply context type %T
- discord: SendImage: invalid reply context type %T
- discord: invalid preview handle type %T
- cron_expr must be a string
- enabled must be a boolean
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/9fccbb4c233203ff.
Report an issue: GitHub.