chenhg5/cc-connect · error
dingtalk: invalid reply context type %T
Error message
dingtalk: invalid reply context type %T
What it means
ReplyWithAt expects its rctx parameter to be the platform-internal replyContext type (the value the platform itself produced when receiving a message). If the caller passes anything else — e.g. a reply context from another platform, a raw string, or a constructed struct of the wrong type — the type assertion fails and this error reports the actual Go type received.
Source
Thrown at platform/dingtalk/dingtalk.go:801
if expiry <= 0 {
slog.Warn("dingtalk: missing/invalid expireIn in token response, defaulting to 7200s", "got", tokenResp.ExpireIn)
expiry = 7200
}
if expiry > 300 {
expiry -= 300 // 5 minute buffer
}
p.tokenExpiry = time.Now().Add(time.Duration(expiry) * time.Second)
slog.Debug("dingtalk: access token refreshed", "expires_at", p.tokenExpiry)
return p.accessToken, nil
}
// ReplyWithAt sends a reply with @mention support. Uses text msgtype (not markdown)
// because only text type supports highlighted/blue @mentions in DingTalk.
func (p *Platform) ReplyWithAt(ctx context.Context, rctx any, content string, atUsers []string, atAll bool) error {
rc, ok := rctx.(replyContext)
if !ok {
return fmt.Errorf("dingtalk: invalid reply context type %T", rctx)
}
if rc.proactive || rc.sessionWebhook == "" {
return p.sendProactiveMessage(ctx, rc, content)
}
payload := map[string]any{
"msgtype": "text",
"text": map[string]string{"content": content},
}
if len(atUsers) > 0 || atAll {
payload["at"] = map[string]any{
"atUserIds": atUsers,
"isAtAll": atAll,
}
}
body, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("dingtalk: marshal reply: %w", err)View on GitHub (pinned to 4000b2338a)
Solutions
- Only pass replyContext values originally produced by the DingTalk platform (from its receive/reply flow), never from other platform adapters.
- Check the reported %T in the message — if it's another platform's type, route the reply through that platform instead.
- Update cc-connect if contexts are persisted/serialized across versions; internal types are not stable across releases.
- If constructing contexts manually, use the exported APIs the platform provides instead of forging internal types.
- Verify via core.Engine Reply APIs rather than calling platform internals directly.
Example fix
// before: passing a foreign context err := dingtalkPlat.ReplyWithAt(ctx, someTelegramCtx, "hi", ats, false) // after: reply through the originating platform/engine err := originatingPlatform.Reply(ctx, replyCtx, "hi")
Defensive patterns
Strategy: type-guard
Validate before calling
if rc, ok := rctx.(platform.replyContext); !ok {
return fmt.Errorf("reply context of type %T is not a dingtalk replyContext", rctx)
} Type guard
func isDingTalkReplyContext(v any) bool {
_, ok := v.(replyContext)
return ok
} Try / catch
if err := p.ReplyWithAt(ctx, rctx, text, ats, false); err != nil {
if strings.Contains(err.Error(), "invalid reply context type") {
// fall back to the engine-level Reply which routes correctly
return engine.Reply(ctx, rctx, text)
}
return err
} Prevention
- Only pass reply contexts produced by the same platform adapter.
- Don't persist reply contexts across cc-connect upgrades — internal types change.
- Prefer core.Engine reply APIs over calling platform internals directly.
- Read the %T value in the error to immediately identify the mismatched type's origin.
When it happens
Trigger: Calling Platform.ReplyWithAt directly with a context obtained from a different platform adapter, from an older cc-connect version with a different internal replyContext layout, or a hand-constructed value rather than one produced by the DingTalk adapter's message receive path.
Common situations: Custom integrations that cache reply contexts across platforms, mixing adapters in one process and passing a telegram/discord reply context to the DingTalk platform, or holding a stale context after an engine restart.
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
- marshal payload: %w
- create request: %w
- dingtalk: SendImage: invalid reply context type %T
- max: unexpected replyCtx type %T
- weixin: invalid reply context
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/7e8a6b951cddbdc2.
Report an issue: GitHub.