{"record":{"id":"cb932bd9fd9698aa","repo":"chenhg5/cc-connect","slug":"get-qrcode-status-http-d-s","errorCode":null,"errorMessage":"get_qrcode_status http %d: %s","messagePattern":"get_qrcode_status http (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cc-connect/weixin.go","lineNumber":492,"sourceCode":"\t\tif errors.As(err, &ne) && ne.Timeout() {\n\t\t\treturn &weixinQRStatusResponse{Status: \"wait\"}, nil\n\t\t}\n\t\treturn nil, err\n\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\")","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/cmd/cc-connect/weixin.go#L474-L510","documentation":"weixinPollQRStatus polls `get_qrcode_status` while waiting for the user to scan the login QR code. On any non-200 HTTP status it returns this error with the status code and a truncated (256-char) body. A single occurrence is often transient; runWeixinQRLoginFlow treats it as a fatal poll failure unless the caller tolerates it.","triggerScenarios":"Polling `ilink/bot/get_qrcode_status` with a qrKey that the server rejects (expired or invalid key), rate limiting (429), or a server error (5xx) during the scan-wait loop.","commonSituations":"QR key expired because the user took too long to scan; server-side throttling from aggressive polling; temporary ilink outage; wrong route tag causing rejection.","solutions":["Retry the whole QR login flow to get a fresh qrKey (keys are short-lived)","If status is 429, back off — reduce polling frequency or wait before retrying","Check the body snippet for an expired/invalid-key message and regenerate the QR code","Verify network/proxy stability for 5xx or gateway errors"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"st, err := weixinPollQRStatus(ctx, apiBase, qrKey, routeTag, debug)\nif err != nil {\n    if isRetryablePollErr(err) { // e.g. 429/5xx in message\n        time.Sleep(backoff); continue\n    }\n    if strings.Contains(err.Error(), \"expired\") { regenerate QR and restart flow }\n    return err\n}","preventionTips":["Scan the QR promptly — qrKeys expire quickly","Poll at a modest interval to avoid 429 throttling","Regenerate the QR code on expired-key errors instead of retrying the same key","Check service status on persistent 5xx"],"tags":["http","polling","weixin","timeout","qr-login"],"backgroundTag":"http-error-response","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"}