{"record":{"id":"2e133433227d4007","repo":"HKUDS/Vibe-Trading","slug":"wechat-session-paused-remaining-min-min-remaini","errorCode":null,"errorMessage":"WeChat session paused, {remaining_min} min remaining (errcode {ERRCODE_SESSION_EXPIRED})","messagePattern":"WeChat session paused, (.+?) min remaining \\(errcode (.+?)\\)","errorType":"error_code","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/src/channels/weixin.py","lineNumber":534,"sourceCode":"    # ------------------------------------------------------------------\n    # Polling  (matches monitor.ts monitorWeixinProvider)\n    # ------------------------------------------------------------------\n\n    def _pause_session(self, duration_s: int = SESSION_PAUSE_DURATION_S) -> None:\n        self._session_pause_until = time.time() + duration_s\n\n    def _session_pause_remaining_s(self) -> int:\n        remaining = int(self._session_pause_until - time.time())\n        if remaining <= 0:\n            self._session_pause_until = 0.0\n            return 0\n        return remaining\n\n    def _assert_session_active(self) -> None:\n        remaining = self._session_pause_remaining_s()\n        if remaining > 0:\n            remaining_min = max((remaining + 59) // 60, 1)\n            raise RuntimeError(\n                f\"WeChat session paused, {remaining_min} min remaining (errcode {ERRCODE_SESSION_EXPIRED})\"\n            )\n\n    async def _poll_once(self) -> None:\n        remaining = self._session_pause_remaining_s()\n        if remaining > 0:\n            await asyncio.sleep(remaining)\n            return\n\n        body: dict[str, Any] = {\n            \"get_updates_buf\": self._get_updates_buf,\n            \"base_info\": BASE_INFO,\n        }\n\n        # Adjust httpx timeout to match the current poll timeout\n        assert self._client is not None\n        self._client.timeout = httpx.Timeout(self._next_poll_timeout_s + 10, connect=30)\n","sourceCodeStart":516,"sourceCodeEnd":552,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/channels/weixin.py#L516-L552","documentation":"Raised by _assert_session_active before any outbound send when the WeChat session is in a timed pause window due to a prior errcode ERRCODE_SESSION_EXPIRED. The channel deliberately stops sending until the pause elapses; the message reports whole minutes remaining (rounded up, min 1).","triggerScenarios":"Calling send() while _session_pause_remaining_s() > 0 — i.e. after a poll returned the session-expired errcode and the channel entered a cooldown pause; any subsequent send attempt during that window raises immediately.","commonSituations":"WeChat login session token expiring mid-run (typically after hours of inactivity or server-side invalidation); the agent queue keeps processing messages during the pause and each send fails; restarting the process without re-login does not clear the pause state.","solutions":["Wait for the indicated remaining minutes, then retry the send.","Trigger a fresh QR login (_qr_login / re-authenticate) to reset the session instead of waiting for the old one.","Drain or defer the outbound queue while the session is paused so sends are not attempted.","Investigate why the session expired (token TTL, concurrent logins invalidating the session) to prevent recurrence."],"exampleFix":"// before\nawait weixin_channel.send(msg)\n\n// after\nif weixin_channel._session_pause_remaining_s() > 0:\n    await queue.put(msg)  # defer until session resumes\nelse:\n    await weixin_channel.send(msg)","handlingStrategy":"fallback","validationCode":"remaining = channel._session_pause_remaining_s() if hasattr(channel, \"_session_pause_remaining_s\") else 0\nif remaining <= 0:\n    await channel.send(msg)\nelse:\n    await deferred_queue.put(msg)","typeGuard":null,"tryCatchPattern":"try:\n    await channel.send(msg)\nexcept RuntimeError as e:\n    if \"session paused\" in str(e):\n        schedule_retry(msg, delay=remaining_seconds_from_message(e))\n    else:\n        raise","preventionTips":["Check _session_pause_remaining_s() before sending.","Keep sessions alive with periodic activity or re-login proactively.","Defer outbound queue during pause windows."],"tags":["wechat","session-expired","cooldown","rate-limit"],"backgroundTag":"session-expired-backoff","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}