Self-Healing CI: Auto-Retrying a Composer GitHub Rate-Limit
A Composer install throttled by the GitHub API hit a temporary quota, not a broken dependency -- the same install succeeds after a short backoff or with a token.
The problem
A composer install fails because GitHub API calls (used to resolve package metadata or source archives) were rate-limited. The packages exist and the lock is valid; the unauthenticated or shared rate window was briefly exceeded. A human waits or adds a token and re-runs, and the install completes unchanged.
Could not fetch https://api.github.com/repos/...: rate limit exceeded.
Create a GitHub OAuth token to go over the API rate limit.Why it happens
Composer resolves some packages through the GitHub API, which enforces per-identity request-rate limits. A build that fans out many metadata calls -- especially unauthenticated -- can briefly exceed the limit even though every package is valid and available.
The limit resets on a rolling window, so a throttled call that fails now succeeds once the rate falls back under the cap, with no change to the dependencies.
The manual fix
Manual mitigations for a Composer rate-limit:
- Re-run after a short wait so the rate window resets.
- Provide a GitHub token so requests count against a higher authenticated limit.
- Prefer dist (zip) downloads and cache Composer’s files to reduce API calls.
composer config -g github-oauth.github.com "${GH_TOKEN}"
composer install --prefer-dist --no-progressHow this gets automated
A rate-limit response carries an unmistakable transient signature and a safe default action: back off and retry. A self-healing CI pipeline recognizes the throttle, waits an appropriate interval, retries resolution, and only escalates if the failure persists after the window should have cleared, distinguishing a temporary quota from a genuine package or auth problem.