{"record":{"id":"50b0720e025f8ae1","repo":"chenhg5/cc-connect","slug":"qqbot-sendwithbuttons-invalid-reply-context-type","errorCode":null,"errorMessage":"qqbot: SendWithButtons: invalid reply context type %T","messagePattern":"qqbot: SendWithButtons: invalid reply context type %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/qqbot/qqbot.go","lineNumber":429,"sourceCode":"\t\t\"media\":    map[string]any{\"file_info\": fileInfo},\n\t}\n\tif rctx.eventMsgID != \"\" {\n\t\tbody[\"msg_id\"] = rctx.eventMsgID\n\t\tbody[\"msg_seq\"] = p.nextMsgSeq(rctx.eventMsgID)\n\t}\n\n\treturn p.apiRequest(\"POST\", url, body)\n}\n\nvar _ core.FileSender = (*Platform)(nil)\nvar _ core.InlineButtonSender = (*Platform)(nil)\n\n// SendWithButtons sends a message with QQ Bot inline keyboard buttons.\n// Implements core.InlineButtonSender.\nfunc (p *Platform) SendWithButtons(ctx context.Context, replyCtx any, content string, buttons [][]core.ButtonOption) error {\n\trctx, ok := replyCtx.(*replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"qqbot: SendWithButtons: invalid reply context type %T\", replyCtx)\n\t}\n\n\t// Use session key from replyContext to embed in button_data\n\tsessionKey := rctx.sessionKey\n\tif sessionKey == \"\" {\n\t\treturn fmt.Errorf(\"qqbot: empty session key in reply context\")\n\t}\n\n\t// Build QQ Bot keyboard rows from button options\n\tvar rows []map[string]any\n\tfor i, row := range buttons {\n\t\tvar btns []map[string]any\n\t\tfor j, btn := range row {\n\t\t\t// Encode decision + session key into button_data so we can route\n\t\t\t// the INTERACTION_CREATE event back to the right session.\n\t\t\t// btn.Data is already \"perm:allow\", \"perm:deny\", or \"perm:allow_all\"\n\t\t\tbuttonData := btn.Data + \":\" + sessionKey\n","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/qqbot/qqbot.go#L411-L447","documentation":"SendWithButtons implements core.InlineButtonSender and expects replyCtx to be a *replyContext internal to the qqbot platform. Any other type (a context from a different platform, a string, nil, etc.) triggers this error (platform/qqbot/qqbot.go:429). It is a defensive type check at the platform boundary.","triggerScenarios":"Calling SendWithButtons on the qqbot Platform while passing a replyCtx value obtained from a different platform's adapter, or a hand-made value that is not *qqbot.replyContext.","commonSituations":"Mixing reply contexts across platforms in custom engine/bridge code; storing replyCtx generically and retrieving the wrong one; calling SendWithButtons with nil after a failed lookup.","solutions":["Only pass the replyCtx value the engine gave you for a message that arrived via the qqbot platform.","Verify which platform produced the replyCtx before dispatching to a platform-specific sender.","Guard with a type assertion yourself if you hold an `any` and skip the call when it is not the qqbot context."],"exampleFix":"// before\nfor _, p := range platforms { p.(core.InlineButtonSender).SendWithButtons(ctx, anyReplyCtx, text, btns) }\n// after\nif _, ok := anyReplyCtx.(*qqbot.ReplyContextLike); ok {\n    sender.(core.InlineButtonSender).SendWithButtons(ctx, anyReplyCtx, text, btns)\n}","handlingStrategy":"type-guard","validationCode":"if _, ok := replyCtx.(*replyContext); !ok {\n    return fmt.Errorf(\"not a qqbot reply context: %T\", replyCtx)\n}","typeGuard":"func isQQBotReplyCtx(v any) bool { _, ok := v.(*replyContext); return ok }","tryCatchPattern":"if err := sender.SendWithButtons(ctx, replyCtx, text, buttons); err != nil {\n    if strings.Contains(err.Error(), \"invalid reply context type\") {\n        slog.Warn(\"wrong platform replyCtx for qqbot sender\", \"type\", fmt.Sprintf(\"%T\", replyCtx))\n    }\n}","preventionTips":["Track which platform each replyCtx came from (wrap it with the platform name).","Never reuse a replyCtx across different platform adapters.","Check core.Platform capabilities with type assertions before calling InlineButtonSender methods."],"tags":["qqbot","type-mismatch","reply-context"],"backgroundTag":"type-mismatch","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}