chenhg5/cc-connect · error

get_bot_qrcode json: %w

Error message

get_bot_qrcode json: %w

What it means

After a successful HTTP 200 from `get_bot_qrcode`, weixinFetchBotQRCode decodes the response body into weixinBotQRResponse with json.Unmarshal. If the body is not valid JSON (or has the wrong types), this error wraps the unmarshal failure. It means the server replied but not with the expected JSON document.

Source

Thrown at cmd/cc-connect/weixin.go:440

}

func weixinFetchBotQRCode(ctx context.Context, apiBase, botType, routeTag string, debug bool) (*weixinBotQRResponse, error) {
	base := strings.TrimRight(apiBase, "/") + "/"
	u, err := url.Parse(base)
	if err != nil {
		return nil, err
	}
	u = u.JoinPath("ilink", "bot", "get_bot_qrcode")
	q := u.Query()
	q.Set("bot_type", botType)
	u.RawQuery = q.Encode()
	raw, err := weixinHTTPGet(ctx, u.String(), routeTag, debug)
	if err != nil {
		return nil, fmt.Errorf("get_bot_qrcode: %w", err)
	}
	var out weixinBotQRResponse
	if err := json.Unmarshal(raw, &out); err != nil {
		return nil, fmt.Errorf("get_bot_qrcode json: %w", err)
	}
	return &out, nil
}

func weixinPollQRStatus(ctx context.Context, apiBase, qrKey, routeTag string, debug bool) (*weixinQRStatusResponse, error) {
	base := strings.TrimRight(apiBase, "/") + "/"
	u, err := url.Parse(base)
	if err != nil {
		return nil, err
	}
	u = u.JoinPath("ilink", "bot", "get_qrcode_status")
	q := u.Query()
	q.Set("qrcode", qrKey)
	u.RawQuery = q.Encode()

	pollCtx, cancel := context.WithTimeout(ctx, weixinQRPollTimeout+2*time.Second)
	defer cancel()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Log/dump the raw response body to see what was actually returned
  2. Check for proxy/captive-portal interference returning HTML with status 200
  3. Compare the response shape against weixinBotQRResponse and update the struct if the API schema changed
  4. Verify the endpoint URL is the real ilink API and not a redirect target
Defensive patterns

Strategy: type-guard

Validate before calling

if !json.Valid(raw) {
    return fmt.Errorf("get_bot_qrcode: non-JSON response: %.100s", raw)
}

Type guard

func looksLikeBotQR(raw []byte) bool {
    var probe struct { QRKey string `json:"qr_key"` }
    return json.Unmarshal(raw, &probe) == nil && probe.QRKey != ""
}

Try / catch

raw, err := weixinHTTPGet(ctx, u, routeTag, debug)
if err != nil { return err }
if !looksLikeBotQR(raw) {
    return fmt.Errorf("get_bot_qrcode: unexpected payload: %.200s", raw)
}

Prevention

When it happens

Trigger: GET to `ilink/bot/get_bot_qrcode` returns 200 with an HTML error page, empty body, or JSON whose fields do not match weixinBotQRResponse's types (e.g. a string where a number is expected).

Common situations: A transparent proxy or captive portal intercepting the request and returning HTML; API version change altering the response schema; wrong endpoint path returning a 200 text page.

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/2459b54cf8755ad9. Report an issue: GitHub.