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

  1. Pass the replyContext value obtained from an inbound envelope (env-based helpers) rather than constructing one ad hoc.
  2. If building one manually, construct platform/tuitui.replyContext{ChatID: ..., ChatType: ..., MessageID: ...} so the assertion succeeds.
  3. Search call sites for typed-nil or wrong-type arguments passed as any and fix the caller's type.
  4. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/a8fcaa38b2ad28b3. Report an issue: GitHub.