GitHub API 401

GitHub API の 401 エラー:原因と解決策

冒頭まとめ GitHub API の 401 Unauthorized は、認証そのものの失敗です。権限の不足ではありません(権限不足は GitHub では 404 または 403 として返ります)。401 の応答の message は2種類しかなく、これが調査の分岐点になります。Requires authentication なら、認証情報がそもそも GitHub に届いていません(原因1)。Bad credentials なら、認証情報は届いたものの、その値が正しくありません(原因2・3)。 Bad credentials の正体は、トークンの誤記や期限切れ・失効のほか、「有効なトークンを設定し直したのに、別の場所(環境変数など)に残った古いトークンが優先され続けている」という取り違えが定番です。どの文言か、そして実際にどのトークンが送られているかを確かめることから始めます。 エラーの概要 401 の応答は次の2種類です(いずれも実際の応答をそのまま確認したものです)。 認証情報なしで認証必須のエンドポイントにアクセスした場合: { "message": "Requires authentication", "documentation_url": "https://docs.github.com/rest", "status": "401" } 認証情報は送ったが、値が正しくない場合: { "message": "Bad credentials", "documentation_url": "https://docs.github.com/rest", "status": "401" } ヘッダーの形式について、公式ドキュメントは、ほとんどの場合 Authorization: Bearer と Authorization: token のどちらでもトークンを渡せる(JSON Web Token を渡す場合のみ Bearer が必須)としています。どちらの形式かが401の原因になることは基本的にありません。また、github.com の API はユーザー名とパスワードによる認証に対応していないため、パスワードでの認証を試みる古いコードは動きません。トークンによる認証が前提です。 まず最初に:message を読み、最小のリクエストで再現する まず message の文言で、認証情報が「届いていない」のか「届いたが不正」なのかを確定します。次に、問題を最小の形で再現します。認証済みユーザー自身の情報を返す /user エンドポイントが最適です。 curl -i -H "Authorization: Bearer <your-github-token>" https://api.github.com/user これが 200 なら、トークン自体は有効です。アプリケーション側で401が出ているなら、アプリケーションが実際に送っているトークンがこれと同じものではない、という取り違え(原因3)に的が絞られます。これが 401 Bad credentials なら、トークンの値そのものの問題です(原因2)。 ...

{
  "message": "Requires authentication",
  "documentation_url": "https://docs.github.com/rest",
2026年1月1日 · ErrorLog
GitHub API 403

GitHub API の 403 エラー:原因と解決策

冒頭まとめ GitHub API の 403 Forbidden は、「権限が足りないとき全般」に返るコードではありません。GitHub は、非公開リソースへの権限不足に対しては存在を隠すために 404 を返す設計であり、classic の personal access token の scope 不足も 404 になります。403 が返るのは、主に次の3つの場面です。第一に、レート制限の超過(403 または 429)。第二に、GitHub App・fine-grained personal access token・Actions の GITHUB_TOKEN の権限不足で、この場合だけ Resource not accessible by integration(または by personal access token)という固有の文言が返ります。第三に、組織が SAML SSO(組織のシングルサインオン)を強制していて、トークンがその組織に対して未承認の場合です。 3つの場面はいずれも応答の message の文言で即座に見分けられます。403 の調査は、設定を触る前に message を読むことから始めます。 エラーの概要 403 は「リクエストは理解したが、実行を拒否した」ことを示すコードです。GitHub API では、拒否の理由が message に明示されるため、文言がそのまま調査の入口になります。実際の403応答の例です。 { "message": "Resource not accessible by integration", "documentation_url": "https://docs.github.com/rest/repos/contents#create-or-update-file-contents" } 見落とされやすいのが 404 との役割分担です。公式のトラブルシューティング文書のとおり、classic トークンの scope 不足や非公開リポジトリへの無権限アクセスは、403 ではなく 404 Not Found として返ります。一方、GitHub App や fine-grained トークンの権限不足は 403 の Resource not accessible 系として返ります。つまり同じ「権限が足りない」でも、トークンの種類によって受け取るコードが変わります。403 を受け取ったという事実自体が、原因の範囲をすでに絞り込んでいます。 ...

{
  "message": "Resource not accessible by integration",
  "documentation_url": "https://docs.github.com/rest/repos/contents#create-or-update-file-contents"
2026年1月1日 · ErrorLog
GitHub API 404

GitHub API の 404 エラー:原因と解決策

冒頭まとめ GitHub API の 404 Not Found には、二重の意味があります。指定したリソースが本当に存在しない場合と、存在するが権限がなくて見せてもらえない場合です。公式ドキュメントに明記されているとおり、GitHub は非公開リポジトリの存在を外部に確認させないために、認証や権限の不備に対して 403 Forbidden ではなく 404 を返す設計を採っています。つまり、リソースがあるはずなのに404が出たら、まず疑うべきは URL ではなく認証と権限です。 原因は3系統に整理できます。URL の指定誤り(タイポ・末尾スラッシュ・エンコード漏れ)、認証の不備(トークン未指定・期限切れ・失効)、そして認証は通っているがトークンの権限が足りない場合です。切り分けの起点は、同じ形のリクエストを条件を変えて比べることです。 エラーの概要 GitHub API の404の応答本文は次の形です。status の値は数値ではなく文字列である点に注意してください。 { "message": "Not Found", "documentation_url": "https://docs.github.com/rest/repos/repos#get-a-repository", "status": "404" } documentation_url は、GitHub がそのリクエストをどのエンドポイントとして解釈したかを示す手がかりです。意図と違うエンドポイントのリファレンスが返ってきている場合は、URL の形そのものを取り違えています。意図どおりのリファレンスが返っているのに404なら、対象の存在か権限の問題です。 権限の問題が404として現れるのは GitHub の意図的な設計です。もし権限不足に403を返すと、404との違いから「そのリポジトリは存在する(が見られない)」という情報が漏れてしまいます。これを防ぐため、非公開リソースへの適切に認証されていないリクエストには、存在しない場合と同じ404を返します。診断する側から見ると、404は「無い」と「見せてもらえない」を区別してくれないコードだ、と理解しておくことが出発点になります。 まず最初に:条件を変えて同じリクエストを比べる 404の原因を推測する前に、2つの比較で範囲を絞れます。 第一に、トークン自体の生死を確認します。認証済みユーザー自身の情報を返すエンドポイントを叩きます。 curl -i -H "Authorization: Bearer <your-github-token>" https://api.github.com/user 200 が返ればトークンは有効です。401 Unauthorized(Bad credentials)が返るなら、トークンの値の誤りや失効であり、404とは別の問題として先に解決します。 第二に、確実に存在する公開リポジトリに対して、調べたいものと同じ形のリクエストを送ります。 curl -i https://api.github.com/repos/octocat/Hello-World これが通るなら URL の組み立て方は正しく、問題は対象リソースの側(存在または権限)に絞られます。これも404になるなら、URL の形そのものを疑います(原因1)。 よくある原因と解決手順 原因1:URL の指定誤り オーナー名・リポジトリ名・ファイルパスの綴りの誤りは、そのまま404になります。ファイル名は思い込みが入りやすい箇所です。たとえば microsoft/vscode リポジトリのライセンスファイルは LICENSE.md ではなく LICENSE.txt であり、拡張子を誤ると404が返ります。 Before(ファイル名の思い込みで404): curl -H "Authorization: Bearer <your-github-token>" \ https://api.github.com/repos/microsoft/vscode/contents/LICENSE.md After(実際のファイル名を確認して指定): curl -H "Authorization: Bearer <your-github-token>" \ https://api.github.com/repos/microsoft/vscode/contents/LICENSE.txt ファイル名の確認には、親ディレクトリの一覧取得(/contents/ をパスなしで叩く)や、ブラウザでのリポジトリの目視が確実です。 ...

{
  "message": "Not Found",
  "documentation_url": "https://docs.github.com/rest/repos/repos#get-a-repository",
2026年1月1日 · ErrorLog
GitHub API 409

GitHub API の 409 エラー:原因と解決策

冒頭まとめ GitHub API の 409 Conflict は、リクエストの綴りや権限の問題ではなく、「リクエストの内容が対象の現在の状態と矛盾している」ことを示すコードです。GitHub 公式の API 定義(OpenAPI)で409が定義されているエンドポイントを調べると、実際の409は3系統に整理できます。第一に、本物のマージ競合です(ブランチのマージ API や上流ブランチとの同期 API が、競合時に409を返すと定義されています)。第二に、競合ガードです。対象が「あなたが見た時点」から動いたことを検出して操作を止める仕組みで、pull request のマージ API に sha を渡した場合の head 不一致や、ファイル更新(contents)API の sha 不一致がこれにあたります。第三に、リポジトリの状態が操作の前提を満たさないケースで、代表は空のリポジトリに対する Git 系・コミット系の API です(公式ガイドに、リポジトリが空または利用不能のとき REST API は 409 Conflict を返すと明記されています)。 同じくらい重要なのが、409だと思い込みやすいのに409ではないエラーです。「Reference already exists」(ブランチやタグが既に存在する)、「No commits between …」(差分のないプルリクエスト作成)、既存タグへのリリース作成は、いずれも 422 Validation Failed です。また、競合状態のプルリクエストをマージしようとした場合は 405 が定義されています。これらを409として調査すると出口のない回り道になるため、まずコードと系統の確認から始めます。 エラーの概要 409は「待てば直る」とも「直らない」とも一概に言えないコードで、系統によって正反対の対処になります。競合ガードの409は、最新の状態を取得し直して再実行するのが正しい対処です。マージ競合の409は、再試行しても同じ結果で、競合の解決そのものが必要です。空リポジトリの409は、初期化するまで何度でも返ります。 実際の応答例として、空のリポジトリのコミット一覧を取得した場合は次の形になります(公開されている実測記録と一致します)。 $ curl -i https://api.github.com/repos/<owner>/<empty-repo>/commits HTTP/2 409 ... { "message": "Git Repository is empty.", "documentation_url": "https://docs.github.com/rest/commits/commits#list-commits" } message の文言が、系統を見分ける最初の手がかりです。Git Repository is empty なら原因3、マージ操作への応答なら原因1か2、ファイル更新への応答なら原因2です。 まず最初に:どの操作への409かで3つに分岐する ブランチのマージ(POST …/merges)や上流との同期(POST …/merge-upstream)への409なら、マージ競合です(原因1)。pull request のマージ(PUT …/pulls/{n}/merge)への409は、リクエストに sha を渡している場合に head の移動を検出したガードです(原因2)。ファイルの作成・更新・削除(PUT / DELETE …/contents/{path})への409も、並行更新による sha の食い違いというガードです(原因2)。コミット一覧や Git データベース系(git/refs、git/commits、git/trees など)の取得・作成への409で、message が Git Repository is empty なら、リポジトリが空です(原因3)。 ...

$ curl -i https://api.github.com/repos/<owner>/<empty-repo>/commits
HTTP/2 409
...
2026年1月1日 · ErrorLog
GitHub API 422

GitHub API の 422 エラー:原因と解決策

冒頭まとめ GitHub API の 422 Unprocessable Entity は、リクエストが JSON として正しく読めたうえで、中身がそのエンドポイントの検証ルールに通らなかったことを示すコードです。GitHub 公式の API 定義(OpenAPI)で数えると、422 を応答として定義するエンドポイントは308あり、全コードの中で最多です。つまり422は特別な異常ではなく、「パラメータを持つ操作の、最もありふれた失敗の形」です。 調査の核は、応答の errors 配列を読むことに尽きます。公式文書のとおり、配列の各要素は resource(どの種類の対象か)、field(どの項目か)、code(何が悪いか)を持ち、code の値は公式に定義されています。missing_field は必須項目の未設定、invalid は項目の形式の不正、already_exists は同じ値を持つ対象が既に存在、missing は指した対象が存在しない、unprocessable は入力を処理できない、そして custom の場合は必ず message が付き、その文言をそのまま読みます。code と field が分かれば、原因はほぼ確定します。 境界も先に引いておきます。本文が JSON として壊れている場合は 400(Problems parsing JSON)で、422の手前の問題です。対象の「今の状態」との矛盾(sha の不一致、空リポジトリ)は 409 です。また、422は形式的な性質として、リクエストを修正しない限り何度送っても同じ結果になります。GitHub 公式の Octokit の retry プラグインも422を再試行の対象外としており、422への正しい反応は再送ではなく修正です。 エラーの概要 422 の応答本文は、公式の API 定義に Validation Error というスキーマとして定義されています。message と documentation_url が必ず含まれ、多くの場合 errors 配列が付きます。配列の各要素で必須なのは code だけで、resource・field・value(実際に送られた値)は項目に応じて付きます。 { "message": "Validation Failed", "errors": [ { "resource": "Issue", "field": "title", "code": "missing_field" } ], "documentation_url": "https://docs.github.com/rest/issues/issues#create-an-issue" } この例は公式文書に掲載されているもので、「Issue の title が未設定」と一行で読めます。もう1つ、errors が文字列の配列だけの簡易な形(Validation Error Simple)も公式定義に存在し、この場合は文字列の文言をそのまま読みます。 ...

{
  "message": "Validation Failed",
  "errors": [
2026年1月1日 · ErrorLog
GitHub API 429

GitHub API の 429 エラー:原因と解決策

冒頭まとめ GitHub API の 429 Too Many Requests は、呼び出しの量が制限を超えたことを示します。重要なのは、制限が2種類あることです。第一に primary rate limit で、時間あたりの総量の上限です。これに達すると応答ヘッダーの x-ratelimit-remaining が 0 になります。第二に secondary rate limit で、短時間の集中(大量の並列リクエスト、作成系操作の連打など)に対する保護です。こちらは残量が残っていても発動し、message に secondary rate limit という文言が入ります。なお、公式ドキュメントのとおり、同じ制限超過が 429 ではなく 403 で返ることもあります(対処は同じです)。 429 を受け取ったときにやってはいけないのが、待たずに再試行を繰り返すことです。対処の順序は、まずヘッダーの指示どおりに待つ、次に認証を付けて上限を上げる、最後に呼び出しそのものを減らす(直列化・条件付きリクエスト・webhook への転換)、です。いずれも公式の指針が明確に定まっています。 エラーの概要 2種類の 429 は、応答の message で見分けられます。 primary rate limit の超過(時間あたりの総量を使い切った場合): { "message": "API rate limit exceeded for user ID <user-id>.", "documentation_url": "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api" } secondary rate limit の超過(短時間の集中に対する保護): { "message": "You have exceeded a secondary rate limit. Please wait a few minutes before you try again.", "documentation_url": "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api" } あわせて読むべきなのが応答ヘッダーです。x-ratelimit-limit が現在の自分の上限、x-ratelimit-remaining が残量、x-ratelimit-reset が残量の回復時刻(UTC の epoch 秒)、x-ratelimit-resource がどの区分(core、search、graphql など)の制限かを示します。retry-after ヘッダーが付いている場合は、その秒数が最優先の待ち時間です。上限の具体的な数値は認証方法などで異なり、変更されることもあるため、この x-ratelimit-limit の実測値と公式のレート制限ドキュメントで確認してください。 ...

{
  "message": "API rate limit exceeded for user ID <user-id>.",
  "documentation_url": "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api"
2026年1月1日 · ErrorLog
GitHub API 500

GitHub API の 500 エラー:原因と解決策

冒頭まとめ GitHub API の 500 Internal Server Error は、リクエストの綴りや認証の問題ではなく、GitHub 側の内部で予期しないエラーが起きたことを示すコードです。クライアント側に起因する問題には別のコードが割り当てられており(トークンの不備は 401、レート制限は 403 または 429、不存在や権限不足は 404、入力の検証エラーは 422)、これらが500として返ることはありません。原因は2系統に整理できます。第一に、GitHub 側の一時的な障害や内部エラーで、散発的に発生し、同じリクエストをやり直すと通ります。大半はこちらです。第二に、特定のリクエストが GitHub 側の不具合を毎回踏んでいるケースで、同じ呼び出しだけが何度でも500になります。 対処もこの2系統で決まります。散発なら、稼働状況の確認と、間隔を空けた再試行です。再現するなら、リクエストを最小化して引き金を特定し、応答に必ず含まれる x-github-request-id を添えて報告します。手元のコードの修正で500が直るのは、この引き金を特定して回避できた場合に限られます。500の調査は「散発か、再現か」の見極めから始めます。 エラーの概要 GitHub の API は、クライアント側で対処すべき問題を 4xx 系の各コードに割り当てる設計です。500 は、その割り当てのどれにも該当しない「GitHub 内部の予期しない失敗」を意味します。応答から得られる手がかりは多くありませんが、1つだけ確実なものがあります。GitHub API のすべての応答には x-github-request-id ヘッダーが含まれます(実測で確認できます)。 $ curl -sI https://api.github.com/repos/<owner>/<repo> | grep -i x-github-request-id x-github-request-id: C005:2D15D8:A1B83BD:2375C5CD:6A57385F この値は、GitHub 側のログでそのリクエストを一意に特定するための参照 ID です。500が続く場合の報告と調査の起点になるため、失敗した応答のこのヘッダーを控えておきます。GraphQL API では、参照 ID がエラーメッセージの本文中に埋め込まれて返ることがあり、その扱いは GitHub API の 502 の記事で説明したものと同じです。 まず最初に:散発か再現かを見極める 500を受け取ったら、コードを変更する前に次の3点を確認します。 第一に、GitHub の稼働状況ページ(https://www.githubstatus.com)を確認します。API のインシデントが進行中なら、原因は自分のリクエストではありません(原因1)。掲載が遅れることもあるため、掲載がないことは障害でないことの証明にはなりません。 第二に、同じリクエストを1回だけ再実行します。通れば散発(原因1)、また500なら再現(原因2)の疑いです。ただし作成・更新・削除の操作は、応答が届かなかっただけで処理自体は完了している可能性を排除できないため、再実行の前に対象(Issue やコメントなど)が実際に作られていないかを確認し、二重実行を避けてください。 第三に、失敗した応答の x-github-request-id と発生時刻を控えます。 よくある原因と解決手順 原因1:GitHub 側の一時的な障害・内部エラー GitHub 側のインフラに問題が起きている間は、正しいリクエストでも500が返ります。稼働状況ページに該当のインシデントが掲載されていれば、手元での対処はなく、復旧を待って再試行します。短時間に散発的な500が集中する場合も、まずこの系統を疑います。 再試行の設計には、GitHub 公式の Octokit の retry プラグインの線引きがそのまま使えます。公式の説明のとおり、このプラグインは500を含むサーバー側エラーを再試行の対象とし(500応答なら最大3回)、400・401・403・404・410・422・451 は再試行しません。つまり GitHub 公式のツールにおいても、500は「待ってやり直す価値があるコード」、上記の 4xx は「やり直しても結果が変わらないコード」という扱いです。自前で再試行を書く場合もこの線引きに従います。 ...

$ curl -sI https://api.github.com/repos/<owner>/<repo> | grep -i x-github-request-id
x-github-request-id: C005:2D15D8:A1B83BD:2375C5CD:6A57385F
2026年1月1日 · ErrorLog
GitHub API 502

GitHub API の 502 エラー:原因と解決策

冒頭まとめ GitHub API の 502 Bad Gateway は、リクエストの綴りや認証の問題ではなく、GitHub 側が時間内に応答を作れなかったことを示すコードです。原因は2系統に整理できます。第一に、GitHub 側の一時的な障害やインシデントです。この場合、手元でできることは稼働状況の確認と、時間をおいた再試行しかありません。第二に、リクエストの処理が重すぎて時間切れになるケースで、特に GraphQL API で複雑なクエリや大量のデータを一度に要求したときに頻発します。こちらは、取得件数を減らす・クエリを分割するという自衛策が有効です。 逆に、トークンの不備は 401、レート制限の超過は 403 または 429、リソースの不存在や権限不足は 404 として返るのが GitHub の仕様であり、これらが502の原因になることはありません。502の調査は、稼働状況と「操作の重さ」の2点から始めます。 エラーの概要 502 Bad Gateway は、GitHub の内部で応答の生成に失敗した、または間に合わなかったことを示します。GraphQL API の場合、実際の報告例に共通する特徴的な応答本文があります。 { "data": "null", "errors": [ { "message": "Something went wrong while executing your query. This may be the result of a timeout, or it could be a GitHub bug. Please include `XXXX:XXXX:XXXXXXX:XXXXXXX:XXXXXXXX` when reporting this issue." } ] } message 内のバッククォートで囲まれた文字列は、そのリクエストを特定するための参照 ID です。GitHub サポートやコミュニティへ報告する際に必要になるため、502が続く場合は控えておきます。文言にあるとおり、この応答は時間切れ(timeout)の可能性を GitHub 自身が示しています。なお、ブラウザの GitHub 上で同種の問題が起きた場合は「We couldn’t respond to your request in time.」という表示になり、これも「時間内に応答できなかった」という同じ状態を指します。 ...

{
  "data": "null",
  "errors": [
2026年1月1日 · ErrorLog
GitHub API 503

GitHub API の 503 エラー:原因と解決策

エラーの概要 GitHub APIにおける503エラーは、GitHubのサービスが一時的に利用不可の状態にあることを示します。このエラーはGitHub側のメンテナンス、インフラストラクチャの過負荷、またはAPI呼び出しの集中に達した場合に発生します。503エラーが返される際には、通常Retry-Afterヘッダーが含まれており、どのくらい待つべきかの秒数目安が提示されます。 実際のエラーメッセージ例 GitHub APIから返される実際の503レスポンスの例を以下に示します。 { "message": "Service Unavailable", "documentation_url": "https://docs.github.com/rest/overview/resources-in-the-rest-api" } cURLやPythonのrequestsライブラリを使用した場合のコンソール出力例: curl -H "Authorization: token <your-github-token>" \ https://api.github.com/user/repos # レスポンス HTTP/1.1 503 Service Unavailable Retry-After: 60 Content-Type: application/json {"message":"Service Unavailable"} よくある原因と解決手順 原因1:GitHub側のメンテナンスまたはシステム障害 GitHubが定期メンテナンスやシステム障害の最中にAPI呼び出しを行うと503エラーが発生します。この場合、ユーザー側では対応できず、GitHub側の復旧を待つ必要があります。 Before(エラーが起きるコード): import requests response = requests.get( 'https://api.github.com/user/repos', headers={'Authorization': f'token <your-github-token>'} ) print(response.json()) # 503エラーで処理が停止 After(修正後): import requests import time def fetch_with_retry(url, token, max_retries=3): headers = {'Authorization': f'token {token}'} retry_count = 0 while retry_count < max_retries: response = requests.get(url, headers=headers) if response.status_code == 503: retry_after = int(response.headers.get('Retry-After', 60)) print(f"503エラー。{retry_after}秒後に再試行します") time.sleep(retry_after) retry_count += 1 elif response.status_code == 200: return response.json() else: raise Exception(f"エラー: {response.status_code}") raise Exception("最大再試行回数に達しました") result = fetch_with_retry('https://api.github.com/user/repos', '<your-github-token>') print(result) 原因2:APIレート制限への抵触 GitHub APIには時間ごとの呼び出し回数制限があります。認証ユーザーは1時間あたり5,000リクエスト、未認証ユーザーは60リクエストに制限されています。この制限に達すると429エラーが返されますが、その直後の集中アクセスによって503エラーが発生する可能性があります。 ...

{
  "message": "Service Unavailable",
  "documentation_url": "https://docs.github.com/rest/overview/resources-in-the-rest-api"
2026年1月1日 · ErrorLog
GitHub API 504

GitHub API の 504 エラー:原因と解決策

冒頭まとめ GitHub API の 504 Gateway Timeout は、GitHub が制限時間内に応答を作り終えられず、リクエストを処理の途中で打ち切ったことを示すコードです。これは公式に明文化された挙動で、GitHub の公式文書(Troubleshooting the REST API)は、処理が10秒を超えるリクエストを打ち切ってタイムアウトの応答と Server Error のメッセージを返すこと、そしてこの制限時間は API の速度と信頼性を守るために予告なく変更されうることを明記しています。原因は2系統に整理できます。第一に、GitHub 側の障害や混雑で、普段は通るリクエストが散発的に時間切れになるケースです。第二に、リクエスト自体が重すぎて、平常時でも制限時間に収まらないケースです。 対処もこの公式文書がそのまま示しています。稼働状況を確認すること、要求を簡素化すること(1ページに100件を要求しているなら件数を減らす)、時間をおいて再試行することの3つです。逆に、トークンの不備は 401、レート制限は 403 または 429、不存在や権限不足は 404 として返るのが GitHub の仕様であり、これらが504の原因になることはありません。また、手元の HTTP クライアントに設定したタイムアウトの発火は、GitHub からコードが返る前に手元で接続を打ち切る動きなので、504とは別の事象です。504の調査は、コードが本当に GitHub から返っているかの確認と、「散発か、重さ由来か」の見極めから始めます。 エラーの概要 GitHub は API リクエストの処理時間に上限を設けており、超過したリクエストを自らの判断で打ち切ります。打ち切られたリクエストへの応答は次のような形になります。 $ curl -i -H "Authorization: Bearer <your-github-token>" \ "https://api.github.com/repos/<owner>/<repo>/commits?per_page=100" HTTP/2 504 ... { "message": "Server Error", "documentation_url": "https://docs.github.com/rest" } この Server Error という文言は、公式文書がタイムアウト応答に伴うと明記しているメッセージです。なお、同じ「時間内に応答を作れなかった」状態は、経路や API の種類によって 502 として現れることもあります。特に GraphQL API の重いクエリの時間切れは、参照 ID 入りのエラーメッセージを伴う 502 の形の報告が多く、その扱いは GitHub API の 502 の記事で説明しています。コードが502でも504でも、時間切れである限り、原因の見極め方と対処(縮小・分割・再試行)は共通です。 まず最初に:3点を確認する 504を受け取ったら、コードを変更する前に次の3点を確認します。 第一に、そのコードが本当に GitHub から返っているかを確認します。手元のクライアントのタイムアウト(curl の –max-time、requests の timeout= など)が先に発火した場合、ステータスコードは受け取れず、例外や接続打ち切りとして現れます。この場合の調査対象は GitHub ではなく、手元の設定と経路です。 第二に、GitHub の稼働状況ページ(https://www.githubstatus.com)を確認します。公式文書も、時間切れが API 側の問題によるものかをこのページで確認するよう案内しています。インシデントが進行中なら原因は自分のリクエストではありません(原因1)。掲載が遅れることもあるため、掲載がないことは障害でないことの証明にはなりません。 ...

$ curl -i -H "Authorization: Bearer <your-github-token>" \
  "https://api.github.com/repos/<owner>/<repo>/commits?per_page=100"
HTTP/2 504
2026年1月1日 · ErrorLog