Skip to content

fix(platforms): treat ret=-2 as stale session when using context_token - #62386

Open
liuhao1024 wants to merge 4 commits into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-62383
Open

fix(platforms): treat ret=-2 as stale session when using context_token#62386
liuhao1024 wants to merge 4 commits into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-62383

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

When a context_token expires, the iLink API can return ret=-2 with errmsg="rate limited" instead of the expected errcode=-14 (session expired). The code previously only recognized "unknown error" as a stale-session signal in _is_stale_session_ret(), causing cron deliveries to fail with repeated rate-limit retries when tokens expire.

This change broadens the _is_stale_session_ret() helper to treat any ret=-2/errcode=-2 as a possible stale-session signal when the request used a context_token, regardless of the errmsg string. The original behavior is preserved for requests without a context_token (e.g., getUpdates long-polling), which prevents false positives in polling scenarios.

Related Issue

Fixes #62383

Type of Change

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

Changes Made

  • Modified _is_stale_session_ret() in gateway/platforms/weixin.py to accept a keyword-only used_context_token parameter (default False)
  • When used_context_token=True, any ret=-2/errcode=-2 returns True (treated as stale session)
  • Updated call site in _poll_loop() (line 1378) to pass used_context_token=False (preserves original behavior)
  • Updated call site in _send_text_chunk() (line 1793) to pass used_context_token=(context_token is not None)
  • Added 4 new regression tests in tests/gateway/test_weixin.py:
    • test_ret_minus_2_with_rate_limited_and_context_token_is_stale: Tests the new behavior
    • test_ret_minus_2_with_freq_limit_without_context_token_is_not_stale: Ensures backward compatibility
    • test_ret_minus_2_without_context_token_preserves_original_behavior: Validates original behavior is preserved
    • test_ret_minus_2_with_any_errmsg_and_context_token_is_stale: Tests that any errmsg with context_token is treated as stale

How to Test

  1. Run the updated test suite for TestIsStaleSessionRet:

    pytest tests/gateway/test_weixin.py::TestIsStaleSessionRet -v

    All 11 tests should pass, including the 4 new tests.

  2. Verify backward compatibility with existing behavior:

    • pytest tests/gateway/test_weixin.py::TestIsStaleSessionRet::test_ret_minus_2_with_freq_limit_is_not_stale passes
    • pytest tests/gateway/test_weixin.py::TestIsStaleSessionRet::test_ret_minus_2_with_unknown_error_is_stale passes
  3. Verify the fix addresses the reported issue:

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes
  • I've tested on my platform: macOS 15.2

Documentation & Housekeeping

  • I've updated relevant 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) — this fix is platform-independent
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

When a context_token expires, the iLink API can return ret=-2 with
errmsg='rate limited' instead of the expected errcode=-14. The code
previously only recognized 'unknown error' as a stale-session signal,
causing cron deliveries to fail with repeated rate-limit retries.

This change broadens the _is_stale_session_ret() helper to treat any
ret=-2/errcode=-2 as a possible stale-session signal when the request
used a context_token, regardless of the errmsg string. The original
behavior is preserved for requests without a context_token (e.g.,
getUpdates long-polling).

Fixes NousResearch#62383
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/wecom WeCom / WeChat Work adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages duplicate This issue or pull request already exists labels Jul 11, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #35714 — both are your own fix PRs for the same bug (stale Weixin/iLink context_token reported as ret=-2 "rate limited" misclassified as a genuine rate limit in _is_stale_session_ret(), silently failing cron/proactive sends; issue #62383 is a dup of the canonical #35713). #35714 (opened 2026-05-31) fixes it by broadening the errmsg allowlist to include "rate limited"; this PR gates on a used_context_token kwarg. Same file, same function, same goal. #35714 is the earlier canonical fix; if this approach is preferred, consider folding it into #35714 and closing the other. Cross-linking so a maintainer can pick.

@liuhao1024

Copy link
Copy Markdown
Contributor Author

Clarification: this is not a duplicate of #35714

These two PRs address different bugs with different solutions:

The approaches are complementary, not duplicates. This PR's used_context_token parameter covers "rate limited", "unknown error", and future iLink error variants that we haven't seen yet, while #35714 only hardcodes known strings.

Both should remain open for review.

@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 targeting the verified stale-token delivery failure. Current main still recognizes only errmsg="unknown error" in _is_stale_session_ret() (gateway/platforms/weixin.py:99-107), so the reported "rate limited" response still reaches the retry/circuit-breaker path (gateway/platforms/weixin.py:1772-1813).

Problems

  • The new used_context_token condition at gateway/platforms/weixin.py:1793 turns every -2 response with a token into a stale session. That bypasses _record_rate_limit_event() and clears the stored token even for the adapter's documented genuine frequency-limit code. Existing tests intentionally model a connected adapter with ctx-token (tests/gateway/test_weixin.py:372) and expect errmsg="frequency limit" to open the breaker (tests/gateway/test_weixin.py:424-441); this PR changes those tests to remove the token rather than retain that case.

Suggested changes

  • Preserve the genuine rate-limit path for token-bearing sends; use a verified discriminator for stale-token -2 responses rather than treating all of them as stale.
  • Add a token-present frequency limit regression test alongside the new stale-session case.

Automated hermes-sweeper review.

ret == SESSION_EXPIRED_ERRCODE
or errcode == SESSION_EXPIRED_ERRCODE
or _is_stale_session_ret(ret, errcode, resp.get("errmsg"))
or _is_stale_session_ret(ret, errcode, resp.get("errmsg"), used_context_token=(context_token is not None))

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.

This makes every -2 response with a stored context token take the token-clearing retry path, so genuine frequency limit responses never reach _record_rate_limit_event(). Current tests model a connected adapter with ctx-token (tests/gateway/test_weixin.py:372) and expect that response to open the circuit (:424-441); this PR removes the token from those tests. Please preserve the genuine rate-limit path for token-bearing sends.

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

Labels

area/sessions Session lifecycle, resume, persistence, history comp/gateway Gateway runner, session dispatch, delivery duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/wecom WeCom / WeChat Work adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Weixin iLink cron delivery fails with ret=-2 'rate limited' when context_token is stale

3 participants