chenhg5/cc-connect · error

get_qrcode_status json: %w

Error message

get_qrcode_status json: %w

What it means

weixinPollQRStatus decodes the 200 response of `get_qrcode_status` into weixinQRStatusResponse. If the body is not valid JSON matching the struct, this error wraps the json.Unmarshal failure. The status endpoint answered but its payload was not the expected JSON.

Source

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

	}
	defer resp.Body.Close()
	body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
	if err != nil {
		return nil, err
	}
	if debug {
		snippet := string(body)
		if len(snippet) > 200 {
			snippet = snippet[:200]
		}
		fmt.Fprintf(os.Stderr, "[debug] poll status -> %d %s\n", resp.StatusCode, strings.TrimSpace(snippet))
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("get_qrcode_status http %d: %s", resp.StatusCode, weixinTruncateBody(body, 256))
	}
	var out weixinQRStatusResponse
	if err := json.Unmarshal(body, &out); err != nil {
		return nil, fmt.Errorf("get_qrcode_status json: %w", err)
	}
	return &out, nil
}

func verifyWeixinToken(ctx context.Context, apiBase, token, routeTag string, debug bool) error {
	base := strings.TrimRight(apiBase, "/") + "/"
	u := strings.TrimRight(base, "/") + "/ilink/bot/getupdates"
	body := []byte(`{"get_updates_buf":"","base_info":{"channel_version":"cc-connect-weixin-setup/1.0"}}`)
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, bytes.NewReader(body))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("AuthorizationType", "ilink_bot_token")
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Length", fmt.Sprintf("%d", len(body)))
	req.Header.Set("X-WECHAT-UIN", randomWeixinUIN())
	if routeTag != "" {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Dump the raw body to inspect the actual payload
  2. Rule out proxies or captive portals returning HTML with 200
  3. Update weixinQRStatusResponse if the ilink API response schema changed
  4. Re-run setup and observe whether the failure is consistent or intermittent
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

func looksLikeQRStatus(body []byte) bool {
    var probe struct { Status int `json:"status"` }
    return json.Unmarshal(body, &probe) == nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "get_qrcode_status json") {
    logBodyForDebug(); return fmt.Errorf("weixin: status endpoint returned unexpected payload")
}

Prevention

When it happens

Trigger: A 200 response from `get_qrcode_status` whose body is HTML, empty, or has fields incompatible with weixinQRStatusResponse during the QR scan polling loop.

Common situations: Proxy/interception returning HTML with a 200 status; ilink API schema change; misconfigured api_base hitting a non-JSON endpoint that always returns 200.

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