Skip to content

fix(weixin): recognize ret=-2 errmsg='unknown error' as stale-session signal (#17228) - #17432

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-090c767a
Apr 29, 2026
Merged

fix(weixin): recognize ret=-2 errmsg='unknown error' as stale-session signal (#17228)#17432
teknium1 merged 2 commits into
mainfrom
hermes/hermes-090c767a

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Weixin cron pushes to inactive chats now recover by stripping the stale context_token and retrying tokenless, instead of being silently dropped.

Root cause: iLink returns ret=-2 errmsg="unknown error" for a stale context_token (same condition as errcode=-14), but the adapter was treating all ret=-2 as a rate limit and exhausting retries with the same bad token. Genuine rate limits are ret=-2 with a different errmsg (e.g. "freq limit") — the two share a code but are distinguishable by errmsg.

Changes

  • gateway/platforms/weixin.py: new _is_stale_session_ret(ret, errcode, errmsg) helper that matches -2 only when errmsg == "unknown error". Wired into both _send_text_chunk (send path) and the poll loop. Genuine rate-limit -2 still takes the existing backoff path.
  • tests/gateway/test_weixin.py: 7-case truth table for the helper — covers stale/rate-limit disambiguation, case-insensitivity, empty errmsg, and non-match on -14.

Validation

Scenario Before After
ret=-2 errmsg="unknown error" (stale token) Rate-limit backoff, retries fail, push dropped Strip context_token, retry tokenless, push succeeds
ret=-2 errmsg="freq limit" (genuine rate limit) Backoff + retry (correct) Backoff + retry (unchanged)
errcode=-14 (documented session expired) Session-expired path (correct) Session-expired path (unchanged)

tests/gateway/test_weixin.py: 49 passed.

Credit

Salvaged from #17287 by @vominh1919 — original commit preserved via cherry-pick. Also closes #16465 by @Grey0202 (submitted first, same root cause, different implementation — blanket -2 matching which would have masked genuine rate limits).

Closes #17228.

vominh1919 and others added 2 commits April 29, 2026 05:01
The Weixin adapter only recognized errcode=-14 as a session-expired
signal. However, iLink also returns ret=-2 with errmsg="unknown error"
for the same underlying condition (stale session). The adapter treated
ret=-2 as a rate-limit, exhausting retries with the same stale
context_token instead of refreshing the session.

Added _is_stale_session_ret() helper that distinguishes ret=-2 with
"unknown error" from genuine rate limits. Updated both the poll loop
and _send_text_chunk to use the helper.

Fixes #17228
Regression test for the ret=-2 / errmsg='unknown error' disambiguation:
- ret=-2 or errcode=-2 with 'unknown error' → stale session (True)
- ret=-2 with 'freq limit' or other errmsg → rate limit (False)
- ret=-14 → not matched here (handled by SESSION_EXPIRED_ERRCODE path)
- Success codes and missing errmsg → False
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery labels Apr 29, 2026
@teknium1
teknium1 merged commit 258755a into main Apr 29, 2026
11 of 12 checks passed
@teknium1
teknium1 deleted the hermes/hermes-090c767a branch April 29, 2026 12:44
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 P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

weixin: cron-initiated push fails with iLink ret=-2 when context_token is stale (not recognized as session-expired)

3 participants