{"record":{"id":"8f7441054af67008","repo":"BigPizzaV3/CodexPlusPlus","slug":"ret-errcode","errorCode":null,"errorMessage":"微信长轮询被拒绝：ret={} errcode={} {}","messagePattern":"微信长轮询被拒绝：ret=(.+?) errcode=(.+?) (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/connect/weixin.rs","lineNumber":239,"sourceCode":"                    ret: 0,\n                    errcode: 0,\n                    errmsg: String::new(),\n                    messages: Vec::new(),\n                    get_updates_buf: get_updates_buf.to_string(),\n                    longpolling_timeout_ms: timeout_ms,\n                });\n            }\n            Err(error) => return Err(error).context(\"微信长轮询请求失败\"),\n        };\n        let (http_status, bytes) =\n            read_response_limited(response, MAX_API_RESPONSE_BYTES, \"微信长轮询\").await?;\n        if !http_status.is_success() {\n            bail!(\"微信长轮询请求失败：HTTP {http_status}\");\n        }\n        let updates: WeixinUpdates =\n            serde_json::from_slice(&bytes).context(\"微信长轮询响应格式无效\")?;\n        if updates.ret != 0 || updates.errcode != 0 {\n            bail!(\n                \"微信长轮询被拒绝：ret={} errcode={} {}\",\n                updates.ret,\n                updates.errcode,\n                updates.errmsg\n            );\n        }\n        Ok(updates)\n    }\n\n    pub async fn send_text_chunks(\n        &self,\n        to_user_id: &str,\n        text: &str,\n        context_token: &str,\n    ) -> anyhow::Result<()> {\n        if context_token.trim().is_empty() {\n            bail!(\"微信回复缺少 context_token\");\n        }","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/connect/weixin.rs#L221-L257","documentation":"The long poll returned 2xx with valid JSON, but the body reports a business-level error: ret is nonzero or errcode is nonzero, with errmsg. This is WeChat-side rejection at the application layer, such as an expired or invalidated token, a session kicked by another login, or a channel_version the gateway no longer accepts, not a transport failure.","triggerScenarios":"get_updates with a token that was invalidated, for example the QR was scanned on another device; the account logged out; CHANNEL_VERSION in the request no longer accepted after a gateway update.","commonSituations":"Two connectors using the same account; WeChat kicked the bot session; gateway update requiring a newer client version.","solutions":["Re-authenticate by scanning a fresh QR code to obtain a new token","Run only one connector instance per account at a time","Update codex-plus-manager so CHANNEL_VERSION matches what the gateway accepts","Decode ret and errcode from the message to confirm the rejection reason"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match client.get_updates(&buf, timeout_ms).await {\n    Ok(u) => u,\n    Err(e) => {\n        let text = e.to_string();\n        if text.contains(\"ret=\") || text.contains(\"errcode=\") {\n            start_relogin_flow().await?; // token-level rejection, re-scan QR\n            continue;\n        }\n        return Err(e);\n    }\n}","preventionTips":["Map ret and errcode to actions: re-login, backoff, or version bump","Run a single connector per WeChat account","Update the manager when the gateway bumps the required channel version"],"tags":["weixin","api-error","long-polling","auth"],"backgroundTag":"wechat-api-error-code","analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}