HKUDS/Vibe-Trading · critical · RuntimeError

Failed to get QR code from WeChat API: {data}

Error message

Failed to get QR code from WeChat API: {data}

What it means

Thrown when the WeChat iLink login API response for a QR-code request contains an empty 'qrcode' field. The library calls the bot_type=3 QR endpoint unauthenticated and expects data.qrcode to be a non-empty ticket string; an empty value means the server did not issue a login QR code, and the full response is embedded for diagnosis.

Source

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

        resp = await self._client.post(url, json=payload, headers=self._make_headers(auth=auth))
        resp.raise_for_status()
        return resp.json()

    # ------------------------------------------------------------------
    # QR Code Login  (matches login-qr.ts)
    # ------------------------------------------------------------------

    async def _fetch_qr_code(self) -> tuple[str, str]:
        """Fetch a fresh QR code. Returns (qrcode_id, scan_url)."""
        data = await self._api_get(
            "ilink/bot/get_bot_qrcode",
            params={"bot_type": "3"},
            auth=False,
        )
        qrcode_img_content = data.get("qrcode_img_content", "")
        qrcode_id = data.get("qrcode", "")
        if not qrcode_id:
            raise RuntimeError(f"Failed to get QR code from WeChat API: {data}")
        return qrcode_id, (qrcode_img_content or qrcode_id)

    async def _qr_login(self) -> bool:
        """Perform QR code login flow. Returns True on success."""
        try:
            refresh_count = 0
            qrcode_id, scan_url = await self._fetch_qr_code()
            self._print_qr_code(scan_url)
            current_poll_base_url = self.config.base_url

            while self._running:
                try:
                    status_data = await self._api_get_with_base(
                        base_url=current_poll_base_url,
                        endpoint="ilink/bot/get_qrcode_status",
                        params={"qrcode": qrcode_id},
                        auth=False,
                    )

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Retry the QR login after a short backoff (30-60s); transient server refusals are common.
  2. Inspect the full response dict in the message: if it is empty/HTML, check network proxy or DNS interception.
  3. Verify the request parameters (bot_type='3', auth=False) match the API version your account/backend supports.
  4. Check WeChat service status and confirm the account is not temporarily blocked from iLink bot login.

Example fix

// before
qrcode_id, img = await self._fetch_qr_code()

// after
for attempt in range(3):
    try:
        qrcode_id, img = await self._fetch_qr_code()
        break
    except RuntimeError:
        if attempt == 2: raise
        await asyncio.sleep(30)
Defensive patterns

Strategy: retry

Try / catch

try:
    qrcode_id, img = await channel._fetch_qr_code()
except RuntimeError as e:
    if "Failed to get QR code" in str(e):
        await asyncio.sleep(30)  # then retry, max N times
    else:
        raise

Prevention

When it happens

Trigger: Calling _fetch_qr_code (via _qr_login) where the POST to the WeChat API returns JSON lacking or with an empty 'qrcode' key — e.g. server-side rate limiting, service outage, changed response schema, or invalid bot_type parameter.

Common situations: Frequent re-logins triggering WeChat rate limits; WeChat iLink API schema changes after a server update; network middleboxes returning an HTML error page parsed as empty data; misconfigured bot credentials causing the server to refuse QR issuance.

Related errors


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