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
- Dump the raw body to inspect the actual payload
- Rule out proxies or captive portals returning HTML with 200
- Update weixinQRStatusResponse if the ilink API response schema changed
- 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
- Rule out HTML-injecting proxies and VPNs
- Log the raw body whenever unmarshal fails
- Keep weixinQRStatusResponse in sync with API schema changes
- Verify api_base resolves to the genuine API host
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
- weixin: getUpdates json: %w
- get_bot_qrcode json: %w
- invalid json response: %w
- weixin: sendMessage: response json: %w: %s
- weixin: getUploadUrl json: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/e3911f3cc03c1b64.
Report an issue: GitHub.