fix(weixin): detect stale context_token when iLink returns "rate limited" (#35949) - #35983
Open
PRATHAMESH75 wants to merge 1 commit into
Open
Conversation
teknium1
reviewed
Jul 13, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for tracing the stale-token path; current main still has the reported outbound classification gap.
Problems
gateway/platforms/weixin.py:99is shared by both outbound sends and long polling. The proposed"rate limited"match at PR line 113 also feedsgetUpdatesatgateway/platforms/weixin.py:1360, which treats a match as session expiry and sleeps for 600 seconds at lines 1361-1364. The send-onlyretried_without_tokenguard does not protect that path.
Suggested changes
- Scope the new
"rate limited"interpretation to_send_text_chunk_locked(gateway/platforms/weixin.py:1772-1788) so polling retains its existing retry/backoff behavior. - Add a send-path regression asserting a
"rate limited"response retries once withcontext_token=None, plus a polling-path regression for the same response.
This is an automated hermes-sweeper review.
| if ret != RATE_LIMIT_ERRCODE and errcode != RATE_LIMIT_ERRCODE: | ||
| return False | ||
| return (errmsg or "").lower() == "unknown error" | ||
| return (errmsg or "").strip().lower() in _STALE_SESSION_ERRMSGS |
Contributor
There was a problem hiding this comment.
_is_stale_session_ret is also called by the getUpdates loop. This makes any long-poll ret=-2, errmsg="rate limited" response take the session-expired branch and sleep 600 seconds; the tokenless retry guard cited here exists only in the send path. Please scope this extra phrase to outbound sendmessage handling.
This was referenced Jul 31, 2026
…ted" iLink's sendmessage endpoint returns ret=-2 with errmsg="rate limited" for an expired context_token, not just "unknown error". The stale-session matcher missed this string, so all outbound sends silently exhausted 4 retries against the dead token; only inbound replies (which refresh the token from the webhook) kept working. Expand _is_stale_session_ret to also match "rate limited". The send loop's existing retried_without_token guard bounds the false-positive cost: a genuine rate-limit at most pays one tokenless retry before falling through to the rate-limit backoff branch. Fixes NousResearch#35949 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PRATHAMESH75
force-pushed
the
fix/weixin-stale-token-rate-limited-35949
branch
from
August 25, 2026 17:00
745b2d7 to
881946e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #35949 — Weixin iLink stale
context_tokenwas misidentified as a rate limit, causing permanent outbound send failure.iLink's
sendmessageendpoint returnsret=-2, errmsg="rate limited"for an expiredcontext_token, not just"unknown error". The stale-session matcher_is_stale_session_retonly recognised"unknown error", so every outbound message exhausted all 4 retries against the dead token. Only inbound replies survived because theyrefresh the token from the incoming webhook.
Fix
case-insensitive comparison preserved).
The send loop at
_send_text_chunk(weixin.py:1640) already guards itself withretried_without_token, so the false-positive cost on a genuine rate-limit is capped at onetokenless retry before falling through to the rate-limit backoff branch. Inbound paths and the
-14SESSION_EXPIRED_ERRCODEpath are untouched.Chose Option B from the issue (expand the matcher) over Option A (treat all
ret=-2as stale) to preserve the existing backoff behavior for genuine throttling.Test plan
TestIsStaleSessionRet::test_ret_minus_2_with_rate_limited_is_stalecovers"rate limited", mixed case, and surrounding whitespace.TestIsStaleSessionRetstill pass (no regression on"unknown error","freq limit", empty errmsg,-14, or success codes).pytest tests/gateway/test_weixin.py::TestIsStaleSessionRet— 8 passed.ret=-2.Workaround (still valid for users on older builds)
Delete the cached token file to force regeneration.