chenhg5/cc-connect · error
qq: invalid reply context
Error message
qq: invalid reply context
What it means
Returned by Platform.Send when the replyCtx argument is not a *replyContext. The Send API accepts an opaque `any` reply context that must be the internal *replyContext type produced by this platform when it received a message; any other value (nil, a string chat ID, a context from another platform) fails the type assertion.
Source
Thrown at platform/qq/qq.go:449
// raw_message fallback (string with CQ codes)
if raw, ok := payload["raw_message"].(string); ok {
textParts = append(textParts, stripCQCodes(raw))
}
}
return strings.TrimSpace(strings.Join(textParts, "")), images, files, audio
}
// Reply sends a message as a reply to an incoming message.
func (p *Platform) Reply(ctx context.Context, replyCtx any, content string) error {
return p.Send(ctx, replyCtx, content)
}
// Send sends a message to the conversation identified by replyCtx.
func (p *Platform) Send(ctx context.Context, replyCtx any, content string) error {
rctx, ok := replyCtx.(*replyContext)
if !ok {
return fmt.Errorf("qq: invalid reply context")
}
params := map[string]any{
"message": content,
}
if rctx.messageType == "group" {
params["group_id"] = rctx.groupID
_, err := p.callAPI("send_group_msg", params)
return err
}
params["user_id"] = rctx.userID
_, err := p.callAPI("send_private_msg", params)
return err
}
// SendImage sends an image to the conversation.View on GitHub (pinned to 4000b2338a)
Solutions
- Pass the replyCtx value exactly as delivered by the platform's inbound message event — do not rebuild it.
- Ensure the value is *qq.replyContext (pointer, from the qq package), not a copy or an interface re-wrap.
- Do not serialize reply contexts across processes; if you must persist routing info, store your own keys and re-resolve via the platform.
- Verify you are calling Send on the same Platform instance that produced the reply context.
Example fix
// before err := platform.Send(ctx, "123456", "hello") // plain string ID // after err := platform.Send(ctx, msg.ReplyCtx(), "hello") // ctx delivered with the inbound message
Defensive patterns
Strategy: type-guard
Type guard
func isQQReplyContext(v any) bool {
_, ok := v.(*replyContext)
return ok
} Try / catch
if err := p.Send(ctx, replyCtx, content); err != nil {
if strings.Contains(err.Error(), "invalid reply context") {
slog.Error("replyCtx lost or wrong type", "type", fmt.Sprintf("%T", replyCtx))
}
return err
} Prevention
- Always pass the replyCtx delivered with the inbound message, untouched
- Never serialize reply contexts across processes or platforms
- Keep one Platform instance per conversation domain
- Assert the concrete type in tests before wiring Send calls
When it happens
Trigger: Calling Send(ctx, replyCtx, content) with replyCtx that is nil, a plain string/int64 conversation ID, a *replyContext value (not pointer), or a reply context obtained from a different platform adapter.
Common situations: Persisting a reply context to JSON and passing the untyped result back; mixing platform adapters (using a Feishu reply context with the QQ platform); hand-crafting a reply context instead of using the one delivered with the inbound message; serialization round-trip that lost the concrete pointer type.
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
- qq: SendImage: invalid reply context type %T
- line: invalid reply context type %T
- qq: SendFile: invalid reply context type %T
- wecom-ws: SendFile: invalid reply context type %T
- weixin: invalid reply context
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/2d28fcc659f55796.
Report an issue: GitHub.