Skip to content

fix(weixin): distinguish ret=-2 'prepare failed' from genuine rate limit (#80125) - #80156

Closed
JonthanaHanh wants to merge 1 commit into
NousResearch:mainfrom
JonthanaHanh:fix/weixin-prepare-failed-not-rate-limit
Closed

JonthanaHanh wants to merge 1 commit into
NousResearch:mainfrom
JonthanaHanh:fix/weixin-prepare-failed-not-rate-limit

Conversation

@JonthanaHanh

Copy link
Copy Markdown

Summary

iLink returns ret=-2 for both rate limits AND parameter errors. When errmsg is "prepare failed", the real cause is a missing/invalid context_token (e.g. fresh account with no inbound messages yet), not frequency limiting.

Previously this was unconditionally treated as a rate limit, opening a 30s circuit breaker and hiding the real cause behind "iLink sendmessage rate limited; cooldown active for 30.0s".

Changes

In _send_text_chunk_locked (gateway/platforms/weixin.py), added a check before the generic rate-limit handler:

  • ret=-2 + errmsg="prepare failed" raises a descriptive RuntimeError immediately: "iLink sendmessage parameter error: prepare failed (likely missing context_token -- user must send an inbound message first or re-pair)"
  • Does NOT trigger the rate-limit circuit breaker
  • Genuine rate limits (ret=-2 with other errmsg values) continue to work as before

Impact

  1. Diagnostics: operators see the real cause instead of a misleading "rate limited" message
  2. Recovery: the error message guides users to send an inbound message or re-pair
  3. No regression: stale session handling (errmsg="unknown error") and genuine rate limits are unchanged

Fixes #80125

iLink returns ret=-2 for both rate limits AND parameter errors. When
errmsg is 'prepare failed', the real cause is a missing/invalid
context_token (e.g. fresh account with no inbound messages yet), not
frequency limiting. Previously this was unconditionally treated as a
rate limit, opening a 30s circuit breaker and hiding the real cause.

Now 'prepare failed' raises a descriptive RuntimeError immediately
without triggering the rate-limit cooldown, so operators can see the
actual problem and know to send an inbound message or re-pair.

Fixes NousResearch#80125
@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 Aug 6, 2026
@alt-glitch

Copy link
Copy Markdown

This was generated by AI during triage.

Duplicate of #80152, the earlier open fix for #80125. Both distinguish iLink ret=-2 with prepare failed from a genuine rate limit so the context-token error is surfaced without opening the cooldown breaker.

@x7peeps

x7peeps commented Aug 8, 2026

Copy link
Copy Markdown

Hi @JonthanaHanh — heads-up that this PR overlaps with #80152 (also open, fixing #80125 with the same approach: treat iLink ret=-2 + "prepare failed" as a missing/invalid context_token parameter error rather than a rate limit).

#80152 is the more complete implementation (unit helper + 8 regression tests covering breaker-not-opened and fail-fast behavior, plus a token_dir hint in the error message), and it's been rebased on latest main. To land the fix once, I'll close this PR in favor of #80152 — happy to reconsider if you'd prefer to merge the changes here instead. Thanks for surfacing the same bug!

@x7peeps

x7peeps commented Aug 9, 2026

Copy link
Copy Markdown

Following up on the overlap note (no reply from the author yet). To keep the fix landing cleanly, this PR should be closed in favor of #80152 — it fixes the same bug (#80125) but with full coverage:

@JonthanaHanh @NousResearch/maintainers — recommend closing this as duplicate of #80152 so the fix lands once. Happy to rebase/merge either direction if the author prefers to keep theirs.

@x7peeps

x7peeps commented Aug 17, 2026

Copy link
Copy Markdown

Hi @JonthanaHanh — this PR and #80152 fix the same root cause (#80125: weixin ret=-2 + "prepare failed" being misreported as rate limit).

Comparing the two objectively:

#80152 #80156
Files gateway/platforms/weixin.py + tests/gateway/test_weixin.py gateway/platforms/weixin.py only
Test coverage Regression tests (asserts prepare failed is NOT treated as rate-limit; real ret=-2 rate-limit still cooldowns) None
Structure Extracts _is_context_token_error_ret() helper + CONTEXT_TOKEN_ERROR_ERRMSG constant Inline check in _send_text_chunk_locked
Base freshness Based on current main —

#80152 is the more complete fix (regression tests + helper abstraction) and already has CI running. Since I can't close a PR I don't own, I'd suggest we keep #80152 and close this one as duplicate — or if you prefer to keep this, let me know and I'll close mine. Either way, thanks for independently catching the same issue!

kshitijk4poor pushed a commit to kshitijk4poor/hermes-agent that referenced this pull request Sep 18, 2026
…ion error, not a rate limit (NousResearch#80125)

iLink answers a bot-initiated send with ret=-2 errmsg="prepare failed" when the
peer's session is not ready (no inbound message yet, or the context token is
gone). That is deterministic: treating it as a frequency limit spent the retry
budget on an error that never clears and opened the 30 s rate-limit breaker for
the whole account, blocking every later send (NousResearch#80125, NousResearch#112709).

After the tokenless re-send (46ab37c) has been tried — or when there is no
token to drop — a stale-session -2 now fails fast with a descriptive
"session not ready" error and never reaches the rate-limit path. The text
avoids the "rate limit" substring classify_send_error keys on.

Salvage of NousResearch#80152 (fail fast + keep the breaker closed); NousResearch#80156 arrived five
minutes later with the same change.

Co-authored-by: RelaxJonh <92573950+RelaxJonh@users.noreply.github.com>
kshitijk4poor pushed a commit that referenced this pull request Sep 18, 2026
…ion error, not a rate limit (#80125)

iLink answers a bot-initiated send with ret=-2 errmsg="prepare failed" when the
peer's session is not ready (no inbound message yet, or the context token is
gone). That is deterministic: treating it as a frequency limit spent the retry
budget on an error that never clears and opened the 30 s rate-limit breaker for
the whole account, blocking every later send (#80125, #112709).

After the tokenless re-send (46ab37c) has been tried — or when there is no
token to drop — a stale-session -2 now fails fast with a descriptive
"session not ready" error and never reaches the rate-limit path. The text
avoids the "rate limit" substring classify_send_error keys on.

Salvage of #80152 (fail fast + keep the breaker closed); #80156 arrived five
minutes later with the same change.

Co-authored-by: RelaxJonh <92573950+RelaxJonh@users.noreply.github.com>
@kshitijk4poor

Copy link
Copy Markdown

Landed on main via #115359 (merge 5db9f02372) with a Co-authored-by for you on the salvaged commit bd39167c56 — #80152 by @x7peeps was opened five minutes earlier with the same change, so it carries the author line. Thank you — closing as merged through the salvage.

xyshanren pushed a commit to xyshanren/hermes-agent-cn that referenced this pull request Sep 20, 2026
…ion error, not a rate limit (NousResearch#80125)

iLink answers a bot-initiated send with ret=-2 errmsg="prepare failed" when the
peer's session is not ready (no inbound message yet, or the context token is
gone). That is deterministic: treating it as a frequency limit spent the retry
budget on an error that never clears and opened the 30 s rate-limit breaker for
the whole account, blocking every later send (NousResearch#80125, NousResearch#112709).

After the tokenless re-send (46ab37c) has been tried — or when there is no
token to drop — a stale-session -2 now fails fast with a descriptive
"session not ready" error and never reaches the rate-limit path. The text
avoids the "rate limit" substring classify_send_error keys on.

Salvage of NousResearch#80152 (fail fast + keep the breaker closed); NousResearch#80156 arrived five
minutes later with the same change.

Co-authored-by: RelaxJonh <92573950+RelaxJonh@users.noreply.github.com>
(cherry picked from commit bd39167)
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 duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/wecom WeCom / WeChat Work adapter 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 adapter: ret=-2 with errmsg 'prepare failed' misreported as 'rate limited', hiding real cause (missing context_token)

5 participants