{"record":{"id":"9fccbb4c233203ff","repo":"chenhg5/cc-connect","slug":"discord-sendfile-invalid-reply-context-type-t","errorCode":null,"errorMessage":"discord: SendFile: invalid reply context type %T","messagePattern":"discord: SendFile: invalid reply context type %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/discord/discord.go","lineNumber":1146,"sourceCode":"\t\t\tslog.Warn(\"discord: interaction file 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 file 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 file: %w\", err)\n\t\t}\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"discord: SendFile: invalid reply context type %T\", rctx)\n\t}\n}\n\nfunc buildDiscordActionRows(rows [][]core.ButtonOption) []discordgo.MessageComponent {\n\tcomponents := make([]discordgo.MessageComponent, 0, len(rows))\n\tfor _, row := range rows {\n\t\tif len(row) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tbuttons := make([]discordgo.MessageComponent, 0, len(row))\n\t\tfor idx, btn := range row {\n\t\t\tstyle := discordgo.SecondaryButton\n\t\t\tswitch idx {\n\t\t\tcase 0:\n\t\t\t\tstyle = discordgo.SuccessButton\n\t\t\tcase 1:\n\t\t\t\tstyle = discordgo.DangerButton\n\t\t\tcase 2:","sourceCodeStart":1128,"sourceCodeEnd":1164,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/discord/discord.go#L1128-L1164","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: wrong type from another platform\np.SendFile(ctx, someOtherPlatformCtx, path)\n// after: use the platform's own reply context\nrc, err := p.ReconstructReplyCtx(sessionKey)\nif err != nil { return err }\nreturn p.SendFile(ctx, rc, path)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isValidDiscordReplyCtx(rctx any) bool {\n    switch rctx.(type) {\n    case replyContext, *interactionReplyCtx:\n        return true\n    }\n    return false\n}","tryCatchPattern":"rc, ok := rctx.(replyContext)\nif !ok {\n    return fmt.Errorf(\"SendFile requires a discord replyContext, got %T\", rctx)\n}\nerr := p.SendFile(ctx, rctx, path)","preventionTips":["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"],"tags":["discord","type-mismatch","programming-error"],"backgroundTag":"incompatible-source-type","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"}