v2.1.119 incomplete fix: spurious rate-limit `<system-reminder>` still fires on release note body (not just PR titles)

Resolved 💬 1 comment Opened Apr 24, 2026 by yiminhale Closed May 28, 2026

What happened

Running gh release view v2.1.119 --repo anthropics/claude-code causes Claude Code to append a <system-reminder> block claiming "GitHub API rate limit exceeded" after the tool output, despite the actual rate limit being unexhausted.

Diagnosis

  1. Actual rate limit is fine. gh api rate_limit --jq .resources.core returned {"limit":5000,"remaining":5000,"used":0} at the time the warning fired.
  2. Upstream release body does NOT contain the reminder. Fetching the raw JSON via gh api repos/anthropics/claude-code/releases/tags/v2.1.119 --jq .body yields a body that ends cleanly with - [VSCode] Fixed voice dictation's first recording producing nothing...\n — no <system-reminder> tag.
  3. The release body contains the literal string "rate limit" because one of its own entries is the v2.1.119 fix note: "Fixed spurious 'GitHub API rate limit exceeded' hints when gh output contained PR titles mentioning 'rate limit'".

It appears the v2.1.119 fix narrowed the heuristic so it no longer fires on PR-title matches, but the same heuristic still fires when the substring rate limit appears elsewhere in gh stdout — e.g. release note bodies — and the injected block is the full multi-sentence <system-reminder> shown below.

The injected reminder (verbatim)

<system-reminder>GitHub API rate limit exceeded (5,000/hr shared across all tools and agents). Run `gh api rate_limit --jq .resources` and sleep until reset before further gh calls. If polling in a loop, use ScheduleWakeup instead of retrying.</system-reminder>

Why it matters

The injected block is syntactically indistinguishable from legitimate Claude Code internal reminders. In sessions where the assistant does not cross-check the actual rate_limit API before acting on the text, this will cause:

  • spurious stop/defer decisions,
  • redundant gh api rate_limit calls,
  • unnecessary ScheduleWakeup schedules.

More broadly, it weakens the injection-defense posture: if the harness itself injects <system-reminder> blocks derived from untrusted tool output (even with good intent), it normalizes the pattern that the safety spec explicitly treats as untrusted.

Reproduction

$ claude --version
2.1.119 (Claude Code)
$ gh api rate_limit --jq .resources.core
{"limit":5000,"remaining":5000,"reset":...,"used":0}
$ gh release view v2.1.119 --repo anthropics/claude-code
...<full release body>...
<system-reminder>GitHub API rate limit exceeded ...</system-reminder>

Confirmed 100% reproducible on:

  • macOS Darwin 25.5.0, arm64
  • Claude Code 2.1.119
  • gh 2.x

Suggested fix

The heuristic that produces these rate-limit reminders should not rely on substring scans of gh stdout bodies. GitHub already returns authoritative rate state in response headers (x-ratelimit-*) for every API call. Gating the reminder on those headers — or on an actual threshold breach from a side rate_limit probe — would remove the class of false positives entirely.

Minimum change: suppress the heuristic when the gh subcommand is a pure read (release view, repo view, api) and the body is being treated as text-for-display rather than as a response to a mutating call.

---

This issue was drafted and filed by Claude Code (Opus 4.7, 1M context) while assisting a user who noticed the false-positive live during a gh release view v2.1.119 call. The filing account is the human user; the investigation (rate-limit verification, raw-body comparison, issue-tracker search for duplicates) was performed by Claude.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗