HKUDS/Vibe-Trading · error · RuntimeError

WeChat session paused, {remaining_min} min remaining (errcod

Error message

WeChat session paused, {remaining_min} min remaining (errcode {ERRCODE_SESSION_EXPIRED})

What it means

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).

Source

Thrown at agent/src/channels/weixin.py:534

    # ------------------------------------------------------------------
    # Polling  (matches monitor.ts monitorWeixinProvider)
    # ------------------------------------------------------------------

    def _pause_session(self, duration_s: int = SESSION_PAUSE_DURATION_S) -> None:
        self._session_pause_until = time.time() + duration_s

    def _session_pause_remaining_s(self) -> int:
        remaining = int(self._session_pause_until - time.time())
        if remaining <= 0:
            self._session_pause_until = 0.0
            return 0
        return remaining

    def _assert_session_active(self) -> None:
        remaining = self._session_pause_remaining_s()
        if remaining > 0:
            remaining_min = max((remaining + 59) // 60, 1)
            raise RuntimeError(
                f"WeChat session paused, {remaining_min} min remaining (errcode {ERRCODE_SESSION_EXPIRED})"
            )

    async def _poll_once(self) -> None:
        remaining = self._session_pause_remaining_s()
        if remaining > 0:
            await asyncio.sleep(remaining)
            return

        body: dict[str, Any] = {
            "get_updates_buf": self._get_updates_buf,
            "base_info": BASE_INFO,
        }

        # Adjust httpx timeout to match the current poll timeout
        assert self._client is not None
        self._client.timeout = httpx.Timeout(self._next_poll_timeout_s + 10, connect=30)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Wait for the indicated remaining minutes, then retry the send.
  2. Trigger a fresh QR login (_qr_login / re-authenticate) to reset the session instead of waiting for the old one.
  3. Drain or defer the outbound queue while the session is paused so sends are not attempted.
  4. Investigate why the session expired (token TTL, concurrent logins invalidating the session) to prevent recurrence.

Example fix

// before
await weixin_channel.send(msg)

// after
if weixin_channel._session_pause_remaining_s() > 0:
    await queue.put(msg)  # defer until session resumes
else:
    await weixin_channel.send(msg)
Defensive patterns

Strategy: fallback

Validate before calling

remaining = channel._session_pause_remaining_s() if hasattr(channel, "_session_pause_remaining_s") else 0
if remaining <= 0:
    await channel.send(msg)
else:
    await deferred_queue.put(msg)

Try / catch

try:
    await channel.send(msg)
except RuntimeError as e:
    if "session paused" in str(e):
        schedule_retry(msg, delay=remaining_seconds_from_message(e))
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/2e133433227d4007. Report an issue: GitHub.