{"record":{"id":"8257779d868deaac","repo":"chenhg5/cc-connect","slug":"qqbot-sendimage-invalid-reply-context-type-t","errorCode":null,"errorMessage":"qqbot: SendImage: invalid reply context type %T","messagePattern":"qqbot: SendImage: invalid reply context type %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/qqbot/qqbot.go","lineNumber":238,"sourceCode":"\tif !ok {\n\t\treturn fmt.Errorf(\"qqbot: invalid reply context\")\n\t}\n\n\tchunks := core.SplitMessageCodeFenceAware(content, messageMaxLen)\n\tfor _, chunk := range chunks {\n\t\tif err := p.sendMessage(rctx, chunk); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// SendImage uploads and sends an image via QQ Bot rich media API.\n// Implements core.ImageSender.\nfunc (p *Platform) SendImage(ctx context.Context, replyCtx any, img core.ImageAttachment) error {\n\trctx, ok := replyCtx.(*replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"qqbot: SendImage: invalid reply context type %T\", replyCtx)\n\t}\n\n\tfileInfo, err := p.uploadRichMedia(rctx, 1, img.Data, \"\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"qqbot: upload image: %w\", err)\n\t}\n\n\tvar url string\n\tswitch rctx.messageType {\n\tcase \"group\":\n\t\turl = fmt.Sprintf(\"%s/v2/groups/%s/messages\", p.apiBase(), rctx.groupOpenID)\n\tcase \"c2c\":\n\t\turl = fmt.Sprintf(\"%s/v2/users/%s/messages\", p.apiBase(), rctx.userOpenID)\n\tdefault:\n\t\treturn fmt.Errorf(\"qqbot: unknown message type %q\", rctx.messageType)\n\t}\n\n\tbody := map[string]any{","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/qqbot/qqbot.go#L220-L256","documentation":"SendImage() (core.ImageSender implementation) also requires replyCtx to be *replyContext. The assertion failure is reported with the unexpected concrete type (%T) to ease debugging. The rich-media upload API needs the group/c2c IDs carried in that context, so sending cannot proceed without it.","triggerScenarios":"Calling SendImage() with nil, a foreign reply-context type, or a context from another platform package.","commonSituations":"An engine feature that assumes all platforms accept the same replyCtx shape; forwarding image attachments across platforms; unit tests passing a stub context instead of the platform's own type.","solutions":["Pass through the unmodified replyCtx obtained from the incoming QQ Bot message event.","Check the %T in the message — it names the wrong type that was actually supplied.","Verify the platform interface dispatch (capability check for core.ImageSender) routes to qqbot, not another adapter.","In tests, construct the context via the platform's own receive path rather than a hand-made struct."],"exampleFix":"// before\nvar ctx any = \"group:ABC123\"\nerr := p.SendImage(context.Background(), ctx, img)\n// after\nctx := msg.ReplyContext() // *replyContext issued by qqbot receive path\nerr := p.SendImage(context.Background(), ctx, img)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"rc, ok := replyCtx.(*replyContext)\nif !ok {\n    return fmt.Errorf(\"SendImage: expected qqbot *replyContext, got %T\", replyCtx)\n}","tryCatchPattern":"if err := p.SendImage(ctx, replyCtx, img); err != nil {\n    if strings.Contains(err.Error(), \"invalid reply context type\") {\n        slog.Error(\"reply ctx from wrong platform\", \"got\", replyCtx)\n    }\n}","preventionTips":["Check core.ImageSender capability on the platform before invoking SendImage.","Store the originating platform with each reply context so dispatch never mixes them.","In tests, build contexts via the platform's receive path, not hand-made structs.","Log %T of the context on mismatch for fast diagnosis."],"tags":["qqbot","type-mismatch","image-upload"],"backgroundTag":"type-mismatch","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"}