Skip to content

fix(weixin): allow tokenless retry when no cached context_token exists - #35066

Open
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/weixin-tokenless-retry-when-no-token
Open

fix(weixin): allow tokenless retry when no cached context_token exists#35066
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/weixin-tokenless-retry-when-no-token

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

Removes the and context_token guard from the tokenless retry branch in _send_text_chunk, allowing cron-initiated pushes to long-inactive WeChat chats to fall back to tokenless sends when no cached context token exists.

Related Issue

Fixes #35062

Type of Change

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

Changes Made

  • gateway/platforms/weixin.py: Remove and context_token from the session-expired retry guard at line 1570 so the tokenless fallback fires regardless of whether a cached token existed.
  • tests/gateway/test_weixin.py: Add TestWeixinTokenlessRetryWithoutCachedToken with two regression tests covering ret=-3 (stale session) and errcode=-14 (classic session expired) when context_token is None.

How to Test

  1. Run pytest tests/gateway/test_weixin.py -xvs -k TestWeixinTokenlessRetryWithoutCachedToken — both new tests should pass.
  2. Run pytest tests/gateway/test_weixin.py -xvs — all 56 tests should pass (no regressions).
  3. Verify the fix logic: when _send_message returns ret=-3, errmsg="unknown error" and context_token=None, the adapter should retry once without a token (the degraded fallback), then succeed on the second attempt.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/gateway/test_weixin.py -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Code Intelligence

  • Analyzed: _send_text_chunk in gateway/platforms/weixin.py (line 1531-1625)
  • Blast radius: LOW — single condition change in one platform adapter's retry path; only affects Weixin/WeChat cron-initiated pushes to inactive chats
  • Related patterns: _is_stale_session_ret() detects ret=-2/-3 with errmsg="unknown error" as stale session signals; the same guard pattern exists in _poll_loop (line 1289) for get_updates, but that path handles session expiry differently (10-minute pause, no token concept)

The tokenless retry guard required context_token to be truthy, which
prevented the fallback from firing during cron-initiated pushes to
long-inactive chats where no cached token existed.  iLink accepts
tokenless sends as a degraded fallback, so the guard now only checks
not retried_without_token.

Fixes NousResearch#35062
@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 May 30, 2026
@drzeast-png

Copy link
Copy Markdown

@liuhao1024 any update on merging this? We've been testing the fix locally and it handles the tokenless edge case correctly. However, there's a deeper ret=-3 issue on cron push that seems to be an iLink platform limitation—see my comment on #35062 for the full analysis. Happy to provide more test data if it helps move this forward.

@liuhao1024

Copy link
Copy Markdown
Contributor Author

Hi @drzeast-png, thanks for testing the fix locally and for the detailed analysis on #35062!

The PR is ready for review — all CI checks are green and it's mergeable. The fix is intentionally scoped to the guard removal only, which handles the case where no cached token exists.

Regarding the deeper issue you mentioned on cron push: I agree that's likely an iLink platform limitation rather than something we can fix in the adapter. The current PR handles the retry-without-token path cleanly, and the with is already detected by as a stale session signal.

Happy to discuss further if you have additional test scenarios.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused retry fix. Current main still has the reported guard at gateway/platforms/weixin.py:1778, so removing it is a valid narrow improvement for errcode=-14 and the established stale-session signal.

Problems

  • The first new test uses ret=-3 (tests/gateway/test_weixin.py:630 in this PR). Current _is_stale_session_ret() only classifies -2 with errmsg='unknown error' as stale (gateway/platforms/weixin.py:99-107), so -3 falls through to the error path at gateway/platforms/weixin.py:1814-1816 even after this guard is removed. The #35062 discussion also reports that tokenless retry does not resolve its observed ret=-3 platform behavior.

Suggested changes

  • Change that fixture to ret=-2, errmsg='unknown error' (or retain only the errcode=-14 case) so the regression test exercises a session-expiry path current main actually recognizes.
  • Keep the one-line guard removal; send() obtains a possibly absent cached token at gateway/platforms/weixin.py:1848 and forwards it to this retry path at 1892-1897.

Automated hermes-sweeper review.

"""Session-expired + no cached token → retry fires, then succeeds."""
adapter = _make_adapter()
adapter._send_session = object()
adapter._token = "test-token"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current _is_stale_session_ret() only treats ret/errcode=-2 with errmsg='unknown error' as stale; ret=-3 falls through to the error path even after this guard removal. Please use the supported -2 stale-session fixture here (the separate errcode=-14 test already covers the other recognized branch).

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 sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Weixin] ret=-3 cron push silently fails after tokenless retry (regression from v0.14)

4 participants