stablyai/orca · warning
GitHub ${bucket} rate limit is low; retry after ${new Date(g
Error message
GitHub ${bucket} rate limit is low; retry after ${new Date(guard.resetAt * 1000).toLocaleTimeString()} What it means
Thrown by assertRateLimitBudget as a client-side pre-flight guard before spending GitHub API quota. When spendsSharedGitHubComQuota is true it refreshes the rate-limit snapshot, then repositoryRateLimitGuard reports blocked=true for the named bucket (core or graphql). The error is proactive — no request has been made yet — and includes the reset time so callers can schedule a retry. It protects a per-user, per-hour budget shared between Orca, the user's own gh CLI, and any other agents.
Source
Thrown at src/main/github/client.ts:249
const oldestKey = repositoryMergeMetadataCache.keys().next().value
if (oldestKey === undefined) {
break
}
repositoryMergeMetadataCache.delete(oldestKey)
}
}
async function assertRateLimitBudget(
bucket: RateLimitBucketKind,
repository?: GitHubApiRepository | null,
executionOptions?: Pick<GhExecOptions, 'cwd' | 'wslDistro'>
): Promise<void> {
if (spendsSharedGitHubComQuota(repository, executionOptions)) {
await getRateLimit()
}
const guard = repositoryRateLimitGuard(repository, bucket, executionOptions)
if (guard.blocked) {
throw new Error(
`GitHub ${bucket} rate limit is low; retry after ${new Date(guard.resetAt * 1000).toLocaleTimeString()}`
)
}
}
// Why: a branch lookup prefers REST but can fall back to `gh pr list` and
// `gh pr view`, so both buckets are guarded and charged. Mirrors the PR refresh
// coordinator's own estimate.
const PR_BRANCH_LOOKUP_BUCKETS = ['core', 'graphql'] as const
/**
* Rate-limit floor for GitHub PR lookups that do not run through the PR refresh
* coordinator's queue (#11532).
*
* The coordinator guards and paces its own background refreshes, but
* `hostedReview:forBranch` polls the same lookup straight from the renderer.
* Ungated, the two paths together could spend the user's entire hourly quota —
* which is per user and shared with their own `gh` and CLI agents.View on GitHub (pinned to 1136503c6a)
Solutions
- Wait until the reset time shown in the message, then retry — the guard will re-evaluate.
- Reduce background refresh frequency in Orca settings to lower steady-state spend.
- If you are running other gh CLI tooling, stagger or pause it.
- For automated jobs, switch to a GitHub App token (higher limits) or use conditional requests / caching.
- Confirm the bucket that is low (core vs graphql) — graphql drains faster for stack-aware PR lookups.
Example fix
// before: caller retries immediately on any error
await lookupPR(number).catch(() => lookupPR(number))
// after: honor the rate-limit reset hint
try {
await lookupPR(number)
} catch (err) {
if (/rate limit is low; retry after/.test(String(err.message))) {
scheduleRetryAfterMessage(err.message)
return
}
throw err
} Defensive patterns
Strategy: retry
Validate before calling
import { getRateLimit } from './client'
async function budgetAllows(bucket: 'core' | 'graphql'): Promise<boolean> {
await getRateLimit() // warm snapshot
return !repositoryRateLimitGuard(undefined, bucket, undefined).blocked
} Type guard
function isRateLimitError(err: unknown): boolean {
return err instanceof Error && /rate limit is low; retry after/.test(err.message)
} Try / catch
try {
await lookupPR(number)
} catch (err) {
if (isRateLimitError(err)) {
const resetAt = parseRetryAfterTime(err.message)
scheduleRetry(resetAt) // do NOT retry immediately
return
}
throw err
} Prevention
- Parse the reset time from the message and schedule, never busy-retry.
- Lower background refresh frequency to reduce steady-state quota spend.
- Stagger other gh CLI tooling against the same token.
When it happens
Trigger: Heavy PR refresh polling combined with renderer-driven branch lookups exhausting the hourly core/graphql budget; a large stack of PRs being refreshed at once; running gh CLI in parallel terminals against the same account; secondary rate limits kicking in near the floor.
Common situations: User runs many parallel gh operations; a monorepo with dozens of open PRs all refreshing; CI or other tooling consuming the same token; an org with strict per-user limits.
Related errors
- Translation request failed with status ${response.status}
- GitHub request failed ${res.status} ${res.statusText}: ${bod
- GitHub releases response for ${repo} was not an array
- repo is required
- token is required
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/bbcce70bfe44e95e.
Report an issue: GitHub.