chenhg5/cc-connect · error

weixin: getUpdates json: %w

Error message

weixin: getUpdates json: %w

What it means

getUpdates fetches new messages from the WeChat iLink bot API and decodes the HTTP body into getUpdatesResp. This error wraps a json.Unmarshal failure, meaning the server returned bytes that are not valid JSON or do not match the expected response schema. It usually indicates a protocol/endpoint mismatch or an HTML error page instead of JSON.

Source

Thrown at platform/weixin/client.go:157

		return nil, err
	}
	raw, err := c.post(ctx, "ilink/bot/getupdates", payload, timeout, "getUpdates")
	if err != nil {
		if ctx.Err() != nil {
			return nil, ctx.Err()
		}
		if errors.Is(err, context.DeadlineExceeded) {
			return &getUpdatesResp{Ret: 0, Msgs: nil, GetUpdatesBuf: buf}, nil
		}
		var ne net.Error
		if errors.As(err, &ne) && ne.Timeout() {
			return &getUpdatesResp{Ret: 0, Msgs: nil, GetUpdatesBuf: buf}, nil
		}
		return nil, err
	}
	var out getUpdatesResp
	if err := json.Unmarshal(raw, &out); err != nil {
		return nil, fmt.Errorf("weixin: getUpdates json: %w", err)
	}
	return &out, nil
}

func (c *apiClient) sendMessage(ctx context.Context, msg *sendMessageReq) error {
	if msg == nil {
		return fmt.Errorf("weixin: sendMessage: nil request")
	}
	msg.BaseInfo = baseInfo{ChannelVersion: channelVersion}
	payload, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	raw, err := c.post(ctx, "ilink/bot/sendmessage", payload, 0, "sendMessage")
	if err != nil {
		return err
	}
	if len(bytes.TrimSpace(raw)) == 0 {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Log the raw response body (truncateForLog) to see what the server actually returned
  2. Verify the bot session/ticket is still valid and re-authenticate if the API changed
  3. Update the getUpdatesResp struct to match the current iLink API schema
  4. Check for proxies/WAFs rewriting responses to HTML and bypass them

Example fix

// before: error hides the body
return nil, fmt.Errorf("weixin: getUpdates json: %w", err)
// after: include a body snippet for diagnosis
return nil, fmt.Errorf("weixin: getUpdates json: %w: %s", err, truncateForLog(raw, 256))
Defensive patterns

Strategy: try-catch

Validate before calling

if len(bytes.TrimSpace(raw)) == 0 { return fmt.Errorf("weixin: empty getUpdates body") }

Type guard

func isJSON(b []byte) bool { var v any; return json.Unmarshal(b, &v) == nil }

Try / catch

out, err := getUpdates(ctx)
if err != nil {
	var jsonErr *json.UnmarshalTypeError
	if errors.As(err, &jsonErr) { slog.Error("weixin: schema drift", "field", jsonErr.Field) }
	else if strings.Contains(err.Error(), "json") { slog.Error("weixin: non-JSON body", "err", err) }
	return
}

Prevention

When it happens

Trigger: The ilink/bot/getupdates endpoint returns malformed JSON, an HTML error page (proxy/gateway error), or a schema change (fields renamed/renumbered) that breaks json.Unmarshal into getUpdatesResp.

Common situations: Running an outdated client against an updated WeChat iLink API; a corporate proxy or WAF injecting an HTML block/login page; capturing a device-routed response that differs from the bot protocol.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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