Summary
When a pull request's webview panel is left open in VS Code after the PR has been closed/merged on GitHub, the extension continues to poll LatestUpdates every webviewRefreshInterval seconds (default: 60s) indefinitely. Each poll consumes a significant number of GraphQL rate limit points proportional to the PR's timeline event count, eventually exhausting the 5,000 points/hour limit.
This is distinct from #7816 (rapid refresh loop on open PR, fixed in v0.120.0) — the polling frequency here is normal (60s), but it never stops even after the PR is closed.
Extension Version
- Extension version: 0.134.0
- VS Code Version: 1.115.0
- OS: macOS (arm64)
- GitHub Product: GitHub.com
Steps to Reproduce
- Open a pull request's description panel in VS Code (click on a PR in the GitHub Pull Requests sidebar)
- Close or merge the pull request on GitHub (via the web UI or
gh CLI)
- Do not close the webview panel in VS Code — leave it open
- Wait 1–2 minutes and observe the extension output log (
Output > GitHub Pull Request)
Expected Behavior
Once a PR is closed/merged, the extension should either:
- Stop polling
LatestUpdates for that panel entirely, or
- Significantly reduce the polling frequency (e.g., fall back to 300s or stop)
Actual Behavior
The extension continues to fire LatestUpdates every 60 seconds indefinitely, regardless of the PR's closed state.
From the extension output log (with githubPullRequests.logLevel: debug):
2026-04-14 18:14:46 [warning] [RateLimit] GraphQL Rate limit remaining: 912, cost: 1, LatestUpdates
2026-04-14 18:15:47 [warning] [RateLimit] GraphQL Rate limit remaining: 784, cost: 1, LatestUpdates
2026-04-14 18:16:48 [warning] [RateLimit] GraphQL Rate limit remaining: 657, cost: 1, LatestUpdates
2026-04-14 18:17:49 [warning] [RateLimit] GraphQL Rate limit remaining: 531, cost: 1, LatestUpdates
2026-04-14 18:18:49 [warning] [RateLimit] GraphQL Rate limit remaining: 405, cost: 1, LatestUpdates
2026-04-14 18:19:50 [warning] [RateLimit] GraphQL Rate limit remaining: 277, cost: 1, LatestUpdates
2026-04-14 18:20:51 [warning] [RateLimit] GraphQL Rate limit remaining: 155, cost: 1, LatestUpdates
2026-04-14 18:21:52 [warning] [RateLimit] GraphQL Rate limit remaining: 21, cost: 1, LatestUpdates
2026-04-14 18:22:52 [error] Error querying GraphQL API (LatestUpdates): API rate limit already exceeded
2026-04-14 18:22:52 [error] [IssueModel] Error fetching timeline events of issue #295 - API rate limit already exceeded
The log shows IssueModel Error fetching timeline events of issue #295 — where PR #295 was closed approximately 6 hours prior. The poll fires exactly every 60 seconds and does not stop.
Rate Limit Impact
Each LatestUpdates call for this closed PR consumes approximately 128 GraphQL points (proportional to the number of timeline events on the PR). At 60-second intervals:
- ~128 pts/min x 60 = ~7,680 pts/hour — exceeds the 5,000 pts/hour limit by itself
- When combined with normal sidebar queries (
MaxPullRequest every few minutes), the rate limit is exhausted within minutes of the session starting
Related: Concurrent call burst (also observed, related to #8621)
In the same session, when a rate limit error occurred during a normal sidebar refresh, the extension fired 15 individual PullRequest queries simultaneously (within 300ms):
2026-04-14 18:23:24.125 [error] Error querying GraphQL API (PullRequest): rate limit already exceeded
2026-04-14 18:23:24.134 [error] Error querying GraphQL API (PullRequest): rate limit already exceeded
2026-04-14 18:23:24.134 [error] Error querying GraphQL API (PullRequest): rate limit already exceeded
2026-04-14 18:23:24.135 [error] Error querying GraphQL API (PullRequest): rate limit already exceeded
2026-04-14 18:23:24.144 [error] Error querying GraphQL API (PullRequest): rate limit already exceeded
... (15 total within 300ms)
This matches the pattern in #8621 and appears to be a separate race condition triggered when the sidebar attempts to reload after a refresh cycle.
Suggested Fix
In pollForUpdates (or wherever LatestUpdates is scheduled), check the PR's state before scheduling the next poll. If state === 'closed' or state === 'merged', either cancel the timer or set the interval to a significantly longer value (e.g., stop entirely or use 3600s).
Summary
When a pull request's webview panel is left open in VS Code after the PR has been closed/merged on GitHub, the extension continues to poll
LatestUpdateseverywebviewRefreshIntervalseconds (default: 60s) indefinitely. Each poll consumes a significant number of GraphQL rate limit points proportional to the PR's timeline event count, eventually exhausting the 5,000 points/hour limit.This is distinct from #7816 (rapid refresh loop on open PR, fixed in v0.120.0) — the polling frequency here is normal (60s), but it never stops even after the PR is closed.
Extension Version
Steps to Reproduce
ghCLI)Output > GitHub Pull Request)Expected Behavior
Once a PR is closed/merged, the extension should either:
LatestUpdatesfor that panel entirely, orActual Behavior
The extension continues to fire
LatestUpdatesevery 60 seconds indefinitely, regardless of the PR's closed state.From the extension output log (with
githubPullRequests.logLevel: debug):The log shows
IssueModel Error fetching timeline events of issue #295— where PR #295 was closed approximately 6 hours prior. The poll fires exactly every 60 seconds and does not stop.Rate Limit Impact
Each
LatestUpdatescall for this closed PR consumes approximately 128 GraphQL points (proportional to the number of timeline events on the PR). At 60-second intervals:MaxPullRequestevery few minutes), the rate limit is exhausted within minutes of the session startingRelated: Concurrent call burst (also observed, related to #8621)
In the same session, when a rate limit error occurred during a normal sidebar refresh, the extension fired 15 individual
PullRequestqueries simultaneously (within 300ms):This matches the pattern in #8621 and appears to be a separate race condition triggered when the sidebar attempts to reload after a refresh cycle.
Suggested Fix
In
pollForUpdates(or whereverLatestUpdatesis scheduled), check the PR'sstatebefore scheduling the next poll. Ifstate === 'closed'orstate === 'merged', either cancel the timer or set the interval to a significantly longer value (e.g., stop entirely or use 3600s).