chenhg5/cc-connect · error
qqbot: SendWithButtons: invalid reply context type %T
Error message
qqbot: SendWithButtons: invalid reply context type %T
What it means
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.
Source
Thrown at platform/qqbot/qqbot.go:429
"media": map[string]any{"file_info": fileInfo},
}
if rctx.eventMsgID != "" {
body["msg_id"] = rctx.eventMsgID
body["msg_seq"] = p.nextMsgSeq(rctx.eventMsgID)
}
return p.apiRequest("POST", url, body)
}
var _ core.FileSender = (*Platform)(nil)
var _ core.InlineButtonSender = (*Platform)(nil)
// SendWithButtons sends a message with QQ Bot inline keyboard buttons.
// Implements core.InlineButtonSender.
func (p *Platform) SendWithButtons(ctx context.Context, replyCtx any, content string, buttons [][]core.ButtonOption) error {
rctx, ok := replyCtx.(*replyContext)
if !ok {
return fmt.Errorf("qqbot: SendWithButtons: invalid reply context type %T", replyCtx)
}
// Use session key from replyContext to embed in button_data
sessionKey := rctx.sessionKey
if sessionKey == "" {
return fmt.Errorf("qqbot: empty session key in reply context")
}
// Build QQ Bot keyboard rows from button options
var rows []map[string]any
for i, row := range buttons {
var btns []map[string]any
for j, btn := range row {
// Encode decision + session key into button_data so we can route
// the INTERACTION_CREATE event back to the right session.
// btn.Data is already "perm:allow", "perm:deny", or "perm:allow_all"
buttonData := btn.Data + ":" + sessionKey
View on GitHub (pinned to 4000b2338a)
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.
Example fix
// before
for _, p := range platforms { p.(core.InlineButtonSender).SendWithButtons(ctx, anyReplyCtx, text, btns) }
// after
if _, ok := anyReplyCtx.(*qqbot.ReplyContextLike); ok {
sender.(core.InlineButtonSender).SendWithButtons(ctx, anyReplyCtx, text, btns)
} Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := replyCtx.(*replyContext); !ok {
return fmt.Errorf("not a qqbot reply context: %T", replyCtx)
} Type guard
func isQQBotReplyCtx(v any) bool { _, ok := v.(*replyContext); return ok } Try / catch
if err := sender.SendWithButtons(ctx, replyCtx, text, buttons); err != nil {
if strings.Contains(err.Error(), "invalid reply context type") {
slog.Warn("wrong platform replyCtx for qqbot sender", "type", fmt.Sprintf("%T", replyCtx))
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- cloud_web: nil reply context
- cloud_web: invalid reply context type %T
- qqbot: invalid reply context
- qqbot: SendImage: invalid reply context type %T
- qqbot: unknown message type %q
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/50b0720e025f8ae1.
Report an issue: GitHub.