chenhg5/cc-connect · error
tuitui: unexpected replyCtx type %T
Error message
tuitui: unexpected replyCtx type %T
What it means
requireReplyContext asserts that the replyCtx passed to a send API is the platform's internal replyContext struct. SendImage, SendFile and sendText all require this concrete type; anything else (nil, a string chat ID, a context from a different platform) fails the assertion. It exists because Tuitui sends always need a chatID and optionally a chatType, which the struct carries.
Source
Thrown at platform/tuitui/tuitui.go:582
return true
}
return p.isRecentOutboundEcho(env)
}
func (p *Platform) sessionKey(env inboundEnvelope) string {
if env.chatType == chatTypeDirect {
return "tuitui:" + env.senderID
}
if p.shareSessionInChannel || env.chatType == chatTypeChannel {
return "tuitui:" + env.chatID
}
return "tuitui:" + env.chatID + ":" + env.senderID
}
func requireReplyContext(replyCtx any) (replyContext, error) {
rctx, ok := replyCtx.(replyContext)
if !ok {
return replyContext{}, fmt.Errorf("tuitui: unexpected replyCtx type %T", replyCtx)
}
if rctx.chatType == "" {
rctx.chatType = guessChatType(rctx.chatID)
}
return rctx, nil
}
func (p *Platform) sendText(ctx context.Context, replyCtx any, content string) error {
rctx, err := requireReplyContext(replyCtx)
if err != nil {
return err
}
payload := map[string]any{
"msgtype": "text",
"text": map[string]string{
"content": content,
},
}View on GitHub (pinned to 4000b2338a)
Solutions
- Pass the replyContext value obtained from an inbound envelope (env-based helpers) rather than constructing one ad hoc.
- If building one manually, construct platform/tuitui.replyContext{ChatID: ..., ChatType: ..., MessageID: ...} so the assertion succeeds.
- Search call sites for typed-nil or wrong-type arguments passed as any and fix the caller's type.
- Wrap the call site in a type check so the wrong type is rejected before reaching the platform.
Example fix
// before p.SendImage(ctx, chatIDString, img) // after rctx := tuitui.ReplyContextFromEnvelope(env) p.SendImage(ctx, rctx, img)
Defensive patterns
Strategy: type-guard
Validate before calling
if rctx, ok := replyCtx.(tuitui.ReplyContext); !ok || rctx.ChatID == "" {
return fmt.Errorf("caller must pass a tuitui replyContext, got %T", replyCtx)
} Type guard
func asReplyContext(v any) (replyContext, bool) {
rc, ok := v.(replyContext)
return rc, ok && rc.chatID != ""
} Prevention
- Never pass raw strings or foreign platform structs as replyCtx
- Type replyCtx parameters as replyContext (not any) in your own wrappers
- Keep a single helper that extracts replyContext from inbound envelopes
When it happens
Trigger: Calling p.SendImage, p.SendFile or p.sendText with a replyCtx argument that is not a platform/tuitui.replyContext value — e.g. nil, a raw chat-ID string, or a reply context struct from another platform package.
Common situations: Wiring a generic bridge that passes reply contexts between platforms; caching a replyCtx as an untyped any and storing the wrong value; calling send helpers directly in tests with hand-built arguments.
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
- bridge: invalid reply context type %T
- bridge: invalid reply context
- tuitui: invalid chat type %q
- wecom-ws: SendImage: 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/a8fcaa38b2ad28b3.
Report an issue: GitHub.