chenhg5/cc-connect · error
weixin: invalid reply context
Error message
weixin: invalid reply context
What it means
resolveReplyContext rejects any replyCtx that is not a non-nil *replyContext pointer. SendImage, SendFile and SendAudio all funnel through this function, so passing any other type (or nil) for the reply context makes media sending fail immediately with this message.
Source
Thrown at platform/weixin/media_outbound.go:44
u, err := url.Parse(rawURL)
if err != nil {
return false
}
host := strings.ToLower(u.Hostname())
return strings.HasSuffix(host, ".weixin.qq.com") || strings.HasSuffix(host, ".wechat.com")
}
type cdnUploadedRef struct {
downloadParam string
aesKey []byte
cipherSize int
rawSize int
}
func (p *Platform) resolveReplyContext(replyCtx any) (*replyContext, error) {
rc, ok := replyCtx.(*replyContext)
if !ok || rc == nil {
return nil, fmt.Errorf("weixin: invalid reply context")
}
if strings.TrimSpace(rc.contextToken) == "" {
rc.contextToken = p.getContextToken(rc.peerUserID)
}
if strings.TrimSpace(rc.contextToken) == "" {
return nil, fmt.Errorf("weixin: missing context_token for peer %q", rc.peerUserID)
}
return rc, nil
}
func (p *Platform) uploadToWeixinCDN(ctx context.Context, to string, plaintext []byte, mediaType int, label string) (*cdnUploadedRef, error) {
if len(plaintext) == 0 {
return nil, fmt.Errorf("weixin: %s: empty payload", label)
}
if strings.TrimSpace(p.cdnBaseURL) == "" {
return nil, fmt.Errorf("weixin: cdn_base_url is empty")
}
rawSize := len(plaintext)View on GitHub (pinned to 4000b2338a)
Solutions
- Pass the *replyContext value that was originally returned/provided by the weixin platform when the inbound message was received.
- Check that you are not passing a value type or a different platform's context type; only *weixin.replyContext is accepted.
- Ensure the replyCtx is non-nil before calling; nil triggers this same error.
Example fix
// before
err := p.SendImage(ctx, someStringCtx, img) // weixin: invalid reply context
// after
rc := &replyContext{peerUserID: peer, contextToken: token}
err := p.SendImage(ctx, rc, img) Defensive patterns
Strategy: type-guard
Validate before calling
if rc, ok := replyCtx.(*weixinReplyContext); !ok || rc == nil { return errors.New("no valid weixin reply context") } Type guard
func isWeixinReplyContext(v any) bool { rc, ok := v.(*replyContext); return ok && rc != nil } Try / catch
if err := p.SendImage(ctx, rc, img); err != nil && strings.Contains(err.Error(), "invalid reply context") { log.Error("wrong replyCtx type passed to weixin SendImage") } Prevention
- Always pass the reply context object handed to you by the weixin platform inbound path
- Never store reply contexts as bare strings or untyped values
- Add a unit test asserting the concrete type passed to Send*
When it happens
Trigger: Calling SendImage/SendFile/SendAudio with replyCtx set to nil, to a different concrete type (e.g. *otherPlatform.ReplyContext, string, struct value), or a typed-nil pointer of another type.
Common situations: Code copied from another platform adapter that passes its own reply-context type; callers that store the context as an interface{} and lose the concrete *replyContext type; passing a value (non-pointer) replyContext.
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: SendWithButtons: invalid reply context type %T
- webex: invalid reply context %T
- weixin: missing context_token for peer %q
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/332929c4f5375468.
Report an issue: GitHub.