plugin-retry.js
Adds automatic, configurable retry handling to Octokit's GitHub API requests.
Repository Health
Technical Analysis
@octokit/plugin-retry is an official Octokit plugin that wraps every outgoing request with automatic retry logic. When a request fails with a server error or a retryable 4xx/5xx status, the plugin schedules a retry with exponential backoff instead of surfacing the failure immediately, which smooths over transient GitHub API instability and secondary rate limits without any extra code in the calling application.
Under the hood it hooks into Octokit’s request and error lifecycle events using bottleneck as a lightweight scheduler, tracks a retry count and backoff delay on the request object, and re-throws once the configured retry budget is exhausted. Consumers install it by composing it onto an Octokit class (Octokit.plugin(retry)) and can tune behavior — enabling/disabling the plugin, the base backoff value, the retry count, and which status codes should never be retried — through a single retry option block.
What You Get
- Automatic retries for server errors and retryable 4xx/5xx responses, skipping ones that should never be retried (400, 401, 403, 404, 410, 422, 451) by default
- Exponential backoff between attempts, computed from the retry count and a configurable base delay
- Per-request overrides via
request: { retries, retryAfter }that bypass the default do-not-retry list entirely - GraphQL-aware handling that detects GitHub’s transient ‘Something went wrong while executing your query’ error and retries it like a 500
- A simple on/off switch (
retry: { enabled: false }) to disable the plugin for a given Octokit instance
Common Use Cases
- Hardening CI/CD bots and GitHub Apps against transient GitHub API 5xx errors and abuse-rate-limit responses
- Building GitHub integrations that need resilient long-running sync jobs (issue/PR mirrors, backup tools) without manual retry code
- Wrapping GraphQL calls to GitHub’s API so intermittent query execution errors don’t fail an entire job
- Tuning retry aggressiveness per-request for expensive or rate-limit-sensitive endpoints while leaving defaults elsewhere
Under The Hood
Architecture
The plugin’s retry() entry point (src/index.ts) merges a default RetryState with any octokitOptions.retry overrides, builds a retryPlugin object exposing retry.retryRequest, and — if enabled — registers two Octokit lifecycle hooks: octokit.hook.error("request", ...) and octokit.hook.wrap("request", ...). errorRequest (src/error-request.ts) inspects a failed request’s status against the configurable doNotRetry list, computes a backoff value, and either re-throws the original error or an augmented one carrying retry metadata. wrapRequest (src/wrap-request.ts) creates a per-request Bottleneck limiter, listens for its failed event to read that retry metadata and return a millisecond delay, and additionally detects GitHub GraphQL’s transient “Something went wrong while executing your query” error inside successful HTTP responses, converting it into a synthetic RequestError fed back through errorRequest so REST and GraphQL failures share one retry path.
Tech Stack
A TypeScript, ESM-only (type: module) package targeting Node >=20 with conditional exports, requiring consumers on moduleResolution: node16. It peer-depends on @octokit/core (>=7) and depends on @octokit/request-error, @octokit/types, and bottleneck for scheduling. Builds run through a custom scripts/build.mjs plus tsc for declaration files; tests run on Vitest with V8 coverage; Prettier enforces formatting as part of pretest; releases are fully automated via semantic-release (commit-analyzer, release-notes-generator, npm, GitHub plugins), and CI includes a CodeQL security-analysis workflow.
Code Quality
Tests in test/retry.test.ts and test/smoke.test.ts exercise the plugin through a TestOctokit composed from a mock-response plugin plus the real retry plugin (test/octokit.ts), asserting on request logs and timings rather than mocking internals directly — a reasonably thorough black-box style for a package this size. Source is fully typed, with explicit RetryOptions/RetryState/RetryPlugin interfaces and a satisfies assertion validating the default state at compile time. Error handling is explicit: isRequestError narrows unknown errors, and unrecognized errors are re-thrown immediately rather than swallowed.
API Design
The public surface is minimal and idiomatic for the Octokit plugin ecosystem — consumers compose it once (Octokit.plugin(retry)) and get sensible defaults with zero required configuration, with per-request overrides available for edge cases. The standout design choice is bridging GraphQL’s in-body error convention into the same retry path as REST status-code errors, letting one mechanism cover both APIs. The underlying retry/backoff technique itself is a well-understood pattern rather than a novel algorithm, so this reads as solid, well-executed developer experience rather than groundbreaking design.
Used by 3 apps in this directory
GraphQL Hive
Developer Tools · Devops · Monitoring
Open-source GraphQL schema registry and observability platform with breaking change detection, federation support, and CI/CD integration for teams of any size.
Infisical
Security · Devops
The open-source platform for secrets, certificates, privileged access, and AI agent security — all in one self-hostable system.
Supabase
Developer Tools · Databases · Search
The open-source Postgres development platform that replaces Firebase with authentication, real-time APIs, edge functions, storage, and vector embeddings — all built on PostgreSQL.