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

冒頭まとめ GH013: Repository rule violations found を検索すると、秘密情報が混ざったときの対処が数多く出てきます。それは3系統あるうちの1つにすぎません。GH013 は ruleset(リポジトリに設定された規則の集まり)に違反したという符号で、中身はブランチやタグへの規則、push そのものへの規則、そして秘密情報の検知に分かれます。 見分ける手がかりは、符号のすぐ下に出ます。GitHub は Review all repository rules at に続けて、そのブランチに効いている規則の一覧を示すURL を返します。公式ドキュメントによれば、この一覧は読み取り権限さえあれば誰でも見られます。管理者に問い合わせる前に、まずここを開けば済みます。 もう1つ、bypass(規則を素通りする許可)についての誤解があります。bypass はアカウントに与える権限ではありません。ruleset は push のたびに、そのとき使われた資格情報の持ち主を bypass 一覧と照合します。だから自分を一覧に入れても、CI が別の身元で push していれば拒まれます。手元では通るのに自動処理では落ちる、という報告のほとんどはこれです。 branch protection との違いも押さえてください。公式ドキュメントは、branch protection の制限が既定では管理権限を持つ人に適用されないと明記しています。ruleset は逆で、bypass 一覧に載せない限り誰も素通りできません。管理者だから通るはずだ、という前提はここで崩れます。 エラーの概要 出力は次の形になります。実際に報告された表示です。 remote: error: GH013: Repository rule violations found for refs/heads/main. remote: Review all repository rules at http://github.com/OWNER/REPO/rules?ref=refs/heads/main remote: remote: - Changes must be made through a pull request. To https://github.com/OWNER/REPO ! [remote rejected] main -> main (push declined due to repository rule violations) error: failed to push some refs to 'https://github.com/OWNER/REPO' 読む場所は2つです。1つ目は Review all repository rules at のURL で、対象のブランチに効いている規則がすべて並びます。2つ目はその下の箇条書きで、実際に違反した規則の名前が入ります。 ...

2026年8月7日 · ErrorLog

GitHub の Repository not found エラー:原因と解決策

冒頭まとめ git の Repository not found は必ず2行で出ますが、その2行は書き手が違います。1行目は GitHub のサーバーが返したレスポンス本文を git がそのまま転記したもので、2行目は git 自身の判断です。書き手を分けて読むと、原因の範囲が一度に絞れます。 決め手は2行目です。git の実装では、fatal: repository '...' not found は HTTP 404 を受け取ったときにしか出ません(remote-curl.c の分岐と http.h の missing__target)。一方、2026年8月7日の実測では、GitHub は未認証のリクエストに 404 ではなく 401 を返しました。この2行が並んだ時点で、認証そのものは成功していて、そのトークンや鍵の持ち主にリポジトリが見えていない、という一点に絞られます。 ここで、よくある誤解が2つ崩れます。綴りの見直しは優先順位が下がります。GitHub は所有者名とリポジトリ名を大文字小文字の違いを無視して解決するため、OCTOCAT/HELLO-WORLD でも通りました(実測で 200)。改名や移管を疑う必要もほとんどありません。旧パスへの git clone・git fetch・git push は新しい場所への操作として動き続ける、と公式ドキュメントが明記しています。 最初に確定させるべきなのは、いま自分がどのアカウントとして GitHub と通信しているかです。HTTPS なら保存済みの資格情報、SSH なら提示している鍵が、その入口になります。 エラーの概要 HTTPS で出る場合、ログは次のようになります。GitHub Actions 上の実際の報告では、git の終了コードは 128 でした。 remote: Repository not found. fatal: repository 'https://github.com/OWNER/REPO.git/' not found URL 末尾のスラッシュは入力の誤りではありません。git は通信前に end_url_with_slash() で末尾を揃えており、揃えた後の値を表示しているだけです。ここを直しても何も変わりません。 SSH の場合は文言が変わります。 ERROR: Repository not found. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. 1行目の ERROR: は GitHub の SSH サーバーが出したものです。2行目以降は git の connect.c にある die_initial_contact() の文言で、相手がプロトコルの応答を1つも返さずに接続を閉じると出ます。SSH に HTTP のステータスコードはないため、判断材料はこの1行だけです。 ...

2026年8月7日 · ErrorLog

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

冒頭まとめ GitHub API の 405 Method Not Allowed は、名前から受ける印象と中身が食い違うコードです。HTTP のメソッドを間違えたという意味ではありません。GitHub 公式の API 定義(OpenAPI)で数えると、405 を応答として定義している操作は全1,209操作のうち3つしかなく、そのうち実務で当たるのは事実上1つ、プルリクエストのマージ(PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge)です。この 405 に付けられた定義文は「マージを実行できない場合」であり、意味は「メソッドが違う」ではなく「今はマージできない」です。 応答本文には、422 のような errors 配列がありません。公式定義でも message と documentation_url の2つだけです。つまり調査は、message の文言を読むことに尽きます。実際に記録されている文言は5系統に整理できます。マージできる状態にない(Pull Request is not mergeable)、base ブランチが動いた(Base branch was modified. Review and try the merge again.)、必須ステータスチェックが未完了、必要なレビューが足りない、そのブランチへ push する権限がない、の5つです。 リトライしてよいかどうかも系統で分かれます。Base branch was modified だけが一時的な状態で、待って再試行するのが正しい対処です。残りは、状態を直さない限り何度送っても同じ結果になります。 境界を先に1つ引いておきます。マージ要求に sha を渡して head が一致しなかった場合は、405 ではなく 409(Head branch was modified. Review and try the merge again.)です。Base と Head の違いしかない文言で、ステータスコードも対処も異なります。 エラーの概要 公式 API 定義におけるマージ操作の 405 は、message と documentation_url を持つだけの単純なスキーマで、例として示されている値は Pull Request is not mergeable です。実際の応答は次の形になります(マージを自動化するボットが記録に残したもので、status はクライアント側が付けた項目です)。 ...

2026年7月26日 · ErrorLog

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

冒頭まとめ GitHub API の 400 Bad Request は、リクエストの形式そのものが壊れていて、サーバーが中身の検証に進めない場合に返されます。公式ドキュメントが 400 として挙げているのは、リクエスト本文が JSON として読めない(Problems parsing JSON)、本文が JSON オブジェクトの形になっていない(Body should be a JSON object)、API バージョン指定のヘッダーに存在しない値を指定した、の3つです。 一方、JSON としては正しく読めたうえで、必須パラメータが足りない・値が仕様に合わないという場合に返るのは、400 ではなく 422 Unprocessable Entity です。400 の調査で最初にすべきことは、設定やパラメータの見直しではなく、応答の message を読んで 400 と 422 のどちらの問題かを確定することです。400 は形式の問題なので、同じリクエストを再試行しても結果は変わりません。修正が必要です。 エラーの概要 GitHub API の 400 の応答本文は次の形です。 { "message": "Problems parsing JSON", "documentation_url": "https://docs.github.com/rest" } 公式のトラブルシューティング文書は、400 と 422 の境界を明確に定めています。リクエスト本文に不正な JSON を送ると 400 と Problems parsing JSON が返ります。エンドポイントが JSON オブジェクトを期待しているのに本文がその形になっていないと 400 と Body should be a JSON object が返ります。これに対し、必須パラメータの省略やパラメータの型の誤りは 422 と Invalid request、リクエストを処理できない場合は 422 と Validation Failed です。つまり「JSON として読めるかどうか」が 400 と 422 のおおまかな境界線です。 ...

2026年1月1日 · ErrorLog

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)。 ...

2026年1月1日 · ErrorLog

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 を受け取ったという事実自体が、原因の範囲をすでに絞り込んでいます。 ...

2026年1月1日 · ErrorLog

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/ をパスなしで叩く)や、ブラウザでのリポジトリの目視が確実です。 ...

2026年1月1日 · ErrorLog

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)。 ...

2026年1月1日 · ErrorLog

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)も公式定義に存在し、この場合は文字列の文言をそのまま読みます。 ...

2026年1月1日 · ErrorLog

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 の実測値と公式のレート制限ドキュメントで確認してください。 ...

2026年1月1日 · ErrorLog