{"record":{"id":"e3911f3cc03c1b64","repo":"chenhg5/cc-connect","slug":"get-qrcode-status-json-w","errorCode":null,"errorMessage":"get_qrcode_status json: %w","messagePattern":"get_qrcode_status json: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cc-connect/weixin.go","lineNumber":496,"sourceCode":"\t}\n\tdefer resp.Body.Close()\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif debug {\n\t\tsnippet := string(body)\n\t\tif len(snippet) > 200 {\n\t\t\tsnippet = snippet[:200]\n\t\t}\n\t\tfmt.Fprintf(os.Stderr, \"[debug] poll status -> %d %s\\n\", resp.StatusCode, strings.TrimSpace(snippet))\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"get_qrcode_status http %d: %s\", resp.StatusCode, weixinTruncateBody(body, 256))\n\t}\n\tvar out weixinQRStatusResponse\n\tif err := json.Unmarshal(body, &out); err != nil {\n\t\treturn nil, fmt.Errorf(\"get_qrcode_status json: %w\", err)\n\t}\n\treturn &out, nil\n}\n\nfunc verifyWeixinToken(ctx context.Context, apiBase, token, routeTag string, debug bool) error {\n\tbase := strings.TrimRight(apiBase, \"/\") + \"/\"\n\tu := strings.TrimRight(base, \"/\") + \"/ilink/bot/getupdates\"\n\tbody := []byte(`{\"get_updates_buf\":\"\",\"base_info\":{\"channel_version\":\"cc-connect-weixin-setup/1.0\"}}`)\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, u, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn err\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"AuthorizationType\", \"ilink_bot_token\")\n\treq.Header.Set(\"Authorization\", \"Bearer \"+token)\n\treq.Header.Set(\"Content-Length\", fmt.Sprintf(\"%d\", len(body)))\n\treq.Header.Set(\"X-WECHAT-UIN\", randomWeixinUIN())\n\tif routeTag != \"\" {","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/cmd/cc-connect/weixin.go#L478-L514","documentation":"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.","triggerScenarios":"A 200 response from `get_qrcode_status` whose body is HTML, empty, or has fields incompatible with weixinQRStatusResponse during the QR scan polling loop.","commonSituations":"Proxy/interception returning HTML with a 200 status; ilink API schema change; misconfigured api_base hitting a non-JSON endpoint that always returns 200.","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"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if !json.Valid(body) {\n    return fmt.Errorf(\"get_qrcode_status: non-JSON body: %.100s\", body)\n}","typeGuard":"func looksLikeQRStatus(body []byte) bool {\n    var probe struct { Status int `json:\"status\"` }\n    return json.Unmarshal(body, &probe) == nil\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"get_qrcode_status json\") {\n    logBodyForDebug(); return fmt.Errorf(\"weixin: status endpoint returned unexpected payload\")\n}","preventionTips":["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"],"tags":["json","unmarshal","weixin","polling"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}