GitHub Actions:「API rate limit exceeded for installation」
トークンの、REST API の1時間あたりの枠が使い切られたので、GitHub がリクエストを断りました。「installation」は、そのトークンがインストール済みの GitHub App のものだという意味です。ワークフローの GITHUB_TOKEN もその1つで、GitHub のドキュメントには、GITHUB_TOKEN は GitHub App のインストールのアクセストークンだ、とあります。actions/create-github-app-token で作るトークンもそうです。
見え方
2026年11月1日、PyPI と npm への公開まで済ませてから最後のステップで失敗したリリースの実行から(gaia #6383):
Run softprops/action-gh-release@v3 ... ⚠️ Unexpected error fetching GitHub release for tag refs/tags/v0.25.4-rc2: HttpError: API rate limit exceeded for installation. ... ##[error]API rate limit exceeded for installation. If you reach out to GitHub Support for help, please include the request ID 5400:96E7A:2806BCA:856BD7E:6AE799AB and timestamp 2026-11-01 19:57:31 UTC. ...
- 「API rate limit exceeded for installation ID <番号>」と出すツールもあります。同じ枠です。
- 応答は 403(ときに 429)で、
x-ratelimit-remaining: 0です。x-ratelimit-resetが、枠が戻る時刻を UTC の epoch 秒で示します。
だれの枠か
GITHUB_TOKEN:GitHub のドキュメントでは、1リポジトリあたり1時間 1,000 リクエスト、GitHub Enterprise Cloud のアカウントに属するリソースなら 15,000 です。リポジトリごとなので、そのリポジトリのすべてのワークフローの実行が、同じ枠から使います。semantic-router #5598 では、90分で372の実行が始まり、プルリクエストを確かめている最中に、コミュニティ向けの自動化が枠を使い切っていました。- GitHub App のインストールのトークン:1時間に最低 5,000。リポジトリが20を超えるインストールや、ユーザーが20人を超える組織では増え(1つ・1人ごとに 50)、上限は 12,500。GitHub Enterprise Cloud なら 15,000 です。そのインストールを使うもの全部で共有します。
- API を呼ぶアクションも数に入ります。同じリポジトリでは、それより前に setup-ffmpeg のステップが同じ枠に当たっていました(gaia #6383)。
ジョブの中で枠を見る
- name: API budget
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: gh api rate_limit --jq '.resources.core | "\(.used)/\(.limit), resets \(.reset | todate)"'
rate_limitを呼んでも、1時間の枠は減りません。- ドキュメントは、
x-ratelimit-*の応答ヘッダーを正とし、リクエストを複数の地域で処理するので値は応答ごとに違うことがある、としています。前に表示した数より、失敗したリクエストのヘッダーを信じます。
呼び出しの行き先
- イベントのたびに、開いているプルリクエストを全部たどるワークフロー。bainluck #11886 では、74のプルリクエストが開いていて、1回の実行がそれを一覧し、1つずつ取り、さらにそれぞれのレビューとファイルを読む、をイベントのたびにしていました。イベントの対象のプルリクエストだけを扱います。
- 同時に多くの実行:続けざまの push、マトリックス、コメントやラベルを付けるボット。API を呼ぶ実行はどれも、同じ枠から使います。
- 失敗するステップは、枠が空のときに頼んだステップというだけで、上のリリースのように、長いワークフローの最後のステップのことがよくあります。
失敗させない書き方
新しい push で要らなくなった実行をキャンセルし、始める実行を減らします:
on:
pull_request:
types: [opened, synchronize, ready_for_review]
paths: ['src/**']
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
- 枠が戻るのを待つのは、近いときだけにします。
x-ratelimit-resetを読み、数分先なら待って1回やり直し、そうでなければわかりやすいメッセージで失敗させます。すぐのやり直しは効きません。actions/github-scriptは、retriesを付けても 403 はやり直しません。403 が既定のretry-exempt-status-codesに入っているからです。 - 重い処理には、別の枠を持つトークンを渡します。自分で作ってインストールした GitHub App を
actions/create-github-app-tokenで使うと、そのインストールの枠は、リポジトリのGITHUB_TOKENの枠とは別です(ksail #7907 での提案)。
- uses: actions/create-github-app-token@v3
id: app-token
with:
client-id: ${{ vars.APP_CLIENT_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- run: gh api "repos/${{ github.repository }}/pulls?state=open&per_page=100" --jq length
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
見分け方
- 「API rate limit exceeded for user ID <番号>.」:個人のアクセストークンです。そのユーザーの枠は1時間 5,000 で、そのユーザーの代わりに動くアプリとも共有です。
- 「API rate limit exceeded for <IP アドレス>. (But here's the good news: Authenticated requests get a higher rate limit. ...)」:トークンがまったく送られておらず、枠は1時間 60 です。
GITHUB_TOKENを設定するよう言うツールが、それでも送っていないことがあります(gooseworks #164)。 - 「You have exceeded a secondary rate limit」:短い時間に多すぎるリクエストで、1時間の枠とは別です。
retry-afterのぶん、または少なくとも1分待ちます。 - 「Resource not accessible by integration」:これも 403 ですが、トークンの権限が足りない場合です(「Resource not accessible by integration」)。
失敗したジョブを IntelliJ IDEA から見るなら
Pipeline Inbox for GitHub Actions Workflows は、Lesstep が作っている JetBrains IDE(2024.1 以降)のプラグインです。すべてのリポジトリの実行を、ジョブ・ステップと一緒に IDE のツールウィンドウに並べ、いまのブランチの実行はステータスバーに出ます。読むのは無料、失敗したジョブの再実行・キャンセル・ワークフローの実行・デプロイのレビューは Pro(月 US$1.50・30日の無料試用つき)です。
GitHub と GitHub Actions は GitHub, Inc. の商標、IntelliJ IDEA は JetBrains s.r.o. の商標です。このページは GitHub, Inc.・JetBrains のいずれとも提携しておらず、承認も受けていません。
ほかに:「Resource not accessible by integration」 · GitHub の「API rate limit exceeded」(トークンあり・なし) · 「Input required and not supplied」 · 止まらない実行と強制キャンセル · IntelliJ IDEA で使える GitHub Actions のプラグインの比較 · English