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

  1. Pass the *replyContext value that was originally returned/provided by the weixin platform when the inbound message was received.
  2. Check that you are not passing a value type or a different platform's context type; only *weixin.replyContext is accepted.
  3. 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

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


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