Skip to content

fix(gateway): treat weixin ret=-2 with empty errmsg as stale context_token - #20797

Closed
XIYBHK wants to merge 1 commit into
NousResearch:mainfrom
XIYBHK:fix/weixin-stale-session-empty-errmsg
Closed

fix(gateway): treat weixin ret=-2 with empty errmsg as stale context_token#20797
XIYBHK wants to merge 1 commit into
NousResearch:mainfrom
XIYBHK:fix/weixin-stale-session-empty-errmsg

Conversation

@XIYBHK

@XIYBHK XIYBHK commented May 6, 2026

Copy link
Copy Markdown

What does this PR do?

_is_stale_session_ret in gateway/platforms/weixin.py only recognized ret=-2 as a stale context_token when errmsg == "unknown error". In the wild, iLink also returns ret=-2 with errmsg=None (empty) for the same stale-session condition. The previous check missed this variant, causing the adapter to fall through to the rate-limit branch and burn all retries against a dead token.

This PR extends the check: if errmsg is empty/None, we return True (stale session). Genuine iLink rate limits always carry a populated errmsg such as "frequency limit" or "too frequently", so the distinction remains reliable.

Related Issue

Fixes #18100. Follow-up to #17228.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • gateway/platforms/weixin.py: extend _is_stale_session_ret to return True when errmsg is empty/None (in addition to the existing "unknown error" match)
  • tests/gateway/test_weixin.py: update TestIsStaleSessionRet — replace the old test_ret_minus_2_with_no_errmsg_is_not_stale (which asserted the now-fixed wrong behavior) with two new regression tests covering None and "" errmsg via both ret and errcode paths

How to Test

  1. Run the unit tests: pytest tests/gateway/test_weixin.py::TestIsStaleSessionRet -v
  2. All 7 cases should pass, including the two new _empty_errmsg_is_stale tests.
  3. To verify end-to-end: trigger a WeChat session expiry (let the iLink token go stale), observe gateway.log — previously you'd see rate limited ... ret=-2 errcode=None errmsg=None repeated until failure; with this fix the adapter correctly detects the stale token and attempts a tokenless retry.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(gateway):)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix (2 files: weixin.py + its test)
  • I've added tests for my changes (updated TestIsStaleSessionRet in test_weixin.py)
  • I've tested on my platform: Ubuntu 22.04 (WSL2)

Documentation & Housekeeping

  • I've updated relevant documentation — N/A (internal helper, no user-facing config change)
  • I've updated cli-config.yaml.example — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md — N/A
  • Cross-platform impact — N/A (WeChat/iLink gateway only)
  • Tool descriptions/schemas — N/A

Screenshots / Logs

Real-world gateway.log showing the bug (before fix):

WARNING  gateway.platforms.weixin: [Weixin] rate limited for o9cq80_r; backing off 3.0s before retry
WARNING  gateway.platforms.weixin: [Weixin] rate limited for o9cq80_r; backing off 3.0s before retry
WARNING  gateway.platforms.weixin: [Weixin] rate limited for o9cq80_r; backing off 3.0s before retry
ERROR    gateway.platforms.weixin: [Weixin] send failed to=o9cq80_r: iLink sendmessage rate limited: ret=-2 errcode=None errmsg=None

After a user-initiated inbound message refreshed the session, the next send went through immediately — confirming this is a stale-session signal, not a genuine frequency cap.

…token

iLink sometimes returns ret=-2 with errmsg=None instead of 'unknown error'.
_is_stale_session_ret only matched the 'unknown error' string, so the empty-
errmsg variant fell through to the rate-limit branch and burned all retries
against a dead token.

Extend the check: if errmsg is empty/None, return True (stale session).
Genuine rate limits always carry a populated errmsg (e.g. 'frequency limit',
'too frequently'), so the distinction remains reliable.

Fixes NousResearch#18100. Follow-up to NousResearch#17228.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery platform/wecom WeCom / WeChat Work adapter labels May 6, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #18105 — both extend _is_stale_session_ret in weixin.py to treat empty/None errmsg on ret=-2 as stale context_token. Both close #18100.

@XIYBHK

XIYBHK commented May 7, 2026

Copy link
Copy Markdown
Author

Confirmed — #18105 (opened 2026-04-30) predates this one and implements the same fix with equivalent behavior (also strips/lowercases and treats "" / "unknown error" alike). Closing in favor of #18105.

I'll move the real-world gateway.log repro and one small test-symmetry suggestion over to #18105 as a review comment so the evidence doesn't get lost.

@XIYBHK

XIYBHK commented May 7, 2026

Copy link
Copy Markdown
Author

Closing as duplicate of #18105 per above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/wecom WeCom / WeChat Work adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

weixin: ret=-2 with empty errmsg also indicates stale context_token (follow-up to #17228)

2 participants