{"record":{"id":"63839843728945f4","repo":"zeroclaw-labs/zeroclaw","slug":"wechat-qr-code-fetch-failed-status-body","errorCode":null,"errorMessage":"WeChat QR code fetch failed ({$status}): {$body}","messagePattern":"WeChat QR code fetch failed \\((.+?)\\): (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/wechat.rs","lineNumber":1661,"sourceCode":"                    \"WeChat QR login gave up after repeated expiry\",\n                );\n                anyhow::bail!(\"{reason}\");\n            }\n\n            // Fetch QR code\n            let qr_url = format!(\"{}?bot_type=3\", self.api_url(\"get_bot_qrcode\"));\n            let resp = self\n                .client\n                .get(&qr_url)\n                .timeout(API_TIMEOUT)\n                .send()\n                .await\n                .with_context(|| wechat_cli_string(\"cli-wechat-qr-fetch-failed\"))?;\n\n            if !resp.status().is_success() {\n                let status = resp.status().to_string();\n                let body = resp.text().await.unwrap_or_default();\n                anyhow::bail!(\n                    \"{}\",\n                    wechat_cli_string_with_args(\n                        \"cli-wechat-qr-fetch-status-failed\",\n                        &[(\"status\", &status), (\"body\", &body)],\n                    )\n                );\n            }\n\n            let qr_data: serde_json::Value = resp.json().await?;\n            let qrcode = qr_data\n                .get(\"qrcode\")\n                .and_then(|v| v.as_str())\n                .with_context(|| {\n                    wechat_cli_string_with_args(\n                        \"cli-wechat-missing-response-field\",\n                        &[(\"field\", \"qrcode\")],\n                    )\n                })?","sourceCodeStart":1643,"sourceCodeEnd":1679,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/wechat.rs#L1643-L1679","documentation":"The QR-fetch step of WeChat login does GET {api_url}/get_bot_qrcode?bot_type=3; a non-2xx response bails with this message, formatted through the cli-wechat-qr-fetch-status-failed i18n key with the HTTP status and body. It is the transport-level failure of obtaining the QR image before login polling begins.","triggerScenarios":"Calling login() when the iLink get_bot_qrcode endpoint returns 401/403 (bad token), 404 (wrong api_url or path), 500/502 (iLink outage), or a proxy error page.","commonSituations":"Channel config pointing at the wrong iLink base URL or missing a path prefix; expired or invalid iLink API token; iLink service down or restarting; a corporate proxy intercepting the request.","solutions":["Verify the channel's api_url resolves to the correct iLink instance and path (the QR endpoint is built from it)","Act on the embedded status: 401/403 → fix the iLink token; 404 → wrong endpoint/path in api_url; 5xx → retry later once the service is healthy","Read the body snippet for the concrete iLink error text before changing anything","Retry login after fixing the underlying cause"],"exampleFix":"# before\n[channels.wechat]\napi_url = \"https://ilink.example\"\n# after\n[channels.wechat]\napi_url = \"https://ilink.example.com/api/\"","handlingStrategy":"retry","validationCode":"// Pre-flight the QR endpoint before entering the login loop\nlet probe = reqwest::Client::new()\n    .get(format!(\"{api_url}/get_bot_qrcode?bot_type=3\"))\n    .send().await?;\nif !probe.status().is_success() {\n    return Err(anyhow::anyhow!(\"fix api_url/token before login\"));\n}","typeGuard":null,"tryCatchPattern":"Branch on the embedded status: 401/403/404 are config errors — stop and fix api_url/token, do not loop; 5xx are transient — retry login with backoff after the service recovers.","preventionTips":["Validate api_url and the iLink token with a cheap health call before enabling the channel","Monitor iLink availability; gate login attempts on it","Wrap login in a bounded retry so a single 5xx does not kill the channel"],"tags":["wechat","login","qr-code","http","api","config"],"backgroundTag":"upstream-api-http-error","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}