{"record":{"id":"0822a7650c890357","repo":"chenhg5/cc-connect","slug":"discord-sendimage-invalid-reply-context-type-t","errorCode":null,"errorMessage":"discord: SendImage: invalid reply context type %T","messagePattern":"discord: SendImage: invalid reply context type %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/discord/discord.go","lineNumber":1090,"sourceCode":"\t\t\tslog.Warn(\"discord: interaction image failed, falling back to channel message\", \"error\", err)\n\t\t\t_, err = p.session.ChannelMessageSendComplex(rc.channelID, &discordgo.MessageSend{\n\t\t\t\tFiles: []*discordgo.File{newFile()},\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"discord: send image fallback: %w\", err)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\tcase replyContext:\n\t\t_, err := p.session.ChannelMessageSendComplex(rc.targetChannelID(), &discordgo.MessageSend{\n\t\t\tFiles: []*discordgo.File{newFile()},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"discord: send image: %w\", err)\n\t\t}\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"discord: SendImage: invalid reply context type %T\", rctx)\n\t}\n}\n\nfunc (p *Platform) SendFile(ctx context.Context, rctx any, file core.FileAttachment) error {\n\tname := file.FileName\n\tif name == \"\" {\n\t\tname = \"attachment\"\n\t}\n\n\tnewFile := func() *discordgo.File {\n\t\treturn &discordgo.File{\n\t\t\tName:        name,\n\t\t\tContentType: file.MimeType,\n\t\t\tReader:      bytes.NewReader(file.Data),\n\t\t}\n\t}\n\n\tswitch rc := rctx.(type) {","sourceCodeStart":1072,"sourceCodeEnd":1108,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/discord/discord.go#L1072-L1108","documentation":"SendImage was called with a reply-context value that is neither *interactionReplyCtx nor replyContext — the only two context types the Discord platform produces. The %T verb prints the offending Go type. This is a programming/contract error in the caller, not a Discord API failure: the message never reached Discord.","triggerScenarios":"Passing nil, a stub, or a reply context minted by another platform (Feishu/Telegram/Slack adapters) into discord.Platform.SendImage; custom engine code fabricating its own context struct.","commonSituations":"Cross-platform message forwarding that carries ReplyCtx values across platform boundaries; engine bugs that drop or replace the context; tests that pass placeholder values.","solutions":["Only pass the ReplyCtx captured from an incoming Discord message into SendImage","Add a nil/type check at the call site and skip or reroute the send if the context is foreign","If bridging platforms, create a Discord-native context for the target channel instead of reusing the foreign one","Enable logging of the %T value to find which code path produced the wrong context"],"exampleFix":"// before\nerr := platform.SendImage(ctx, msg.ReplyCtx, img) // ReplyCtx may be foreign\n// after\nif _, ok := msg.ReplyCtx.(discord.ReplyContext); !ok {\n    return fmt.Errorf(\"cannot send image: not a discord reply context\")\n}\nerr := platform.SendImage(ctx, msg.ReplyCtx, img)","handlingStrategy":"type-guard","validationCode":"if rctx == nil {\n    return fmt.Errorf(\"cannot send image: missing discord reply context\")\n}","typeGuard":"func isDiscordImageCtx(rctx any) bool {\n    switch rctx.(type) {\n    case *interactionReplyCtx, replyContext:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"if err := p.SendImage(ctx, rctx, img); err != nil {\n    if strings.Contains(err.Error(), \"invalid reply context type\") {\n        slog.Warn(\"skipping image send: foreign context\", \"type\", fmt.Sprintf(\"%T\", rctx))\n        return nil\n    }\n    return err\n}","preventionTips":["Route SendImage only with contexts produced by discord message handlers","Type-assert contexts at platform boundaries","Keep a platform tag on reply contexts in cross-platform bridges","Unit-test that engine routing never leaks foreign contexts into SendImage"],"tags":["discord","type-mismatch","programming-error"],"backgroundTag":"invalid-argument-value","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}