claude-code-actionのsetup-bunがGHESで壊れたv1.0.42の不具合と現状
claude-code-action v1.0.42でsetup-bunがGitHub Enterprise Serverで401になる既知の不具合の原因と、現在のmainで再現しない理由をまとめます。
anthropics/claude-code-actionのv1.0.42で、内部でBunを入れるsetup-bunステップがGitHub Enterprise Server(GHES)環境で401エラーになる不具合が報告されました。issue #896は2026年2月3日の報告から開いたままで、claude-code-action側の修正案3件もマージされていません。それでも現在のmainでは、別の変更の副産物としてこの401が起きない状態です。本記事では発生条件・原因・現状を、各リポジトリのコード差分と時系列から読み解きます。
v1.0.42で何が起きたか
claude-code-actionは実行時にBunをoven-sh/setup-bunアクションで入れます。2026年2月1日にマージされた#861は、Bunのリリースタグ取得でAPIレート制限に当たる問題を避けるため、GitHubトークンをsetup-bunへ渡すようにしました。この変更が入ったのがv1.0.42です。
#861の狙いは妥当でした。GitHub APIは未認証だと1時間あたり60リクエストに制限され、認証済みなら5,000リクエストまで緩みます。#901の説明には、共有ランナーで未認証のリクエストが403のレート制限に当たったとあります。
ところがGHESで実行すると、setup-bunステップが401で失敗するようになりました。報告者(ef-trss)は、公式手順どおりにGHESへセットアップしても、v1.0.42でsetup-bunのインストールが壊れると書いています。#861の作者のpeloyejeは、社内テストでこのバグに気づいたものの、最後の修正をPRに反映する前にマージされたと説明しています。
エラーメッセージと発生条件
issueのコメント欄(uda832)に貼られたログには、次のエラーが残っています。
Error: Error: Failed to fetch url https://api.github.com/repos/oven-sh/bun/git/refs/tags. (status code: 401, status text: Unauthorized)
{
"message": "Bad credentials",
"documentation_url": "https://docs.github.com/rest",
"status": "401"
}同じsetup-bunステップの失敗でも、ログの文言で原因を切り分けられます。上のBad credentials(401)は、GHES向けのトークンがgithub.comに届いた場合です。#901の説明文にあるAPI rate limit exceeded for <IP>(403)は、トークンなしで未認証のリクエストが上限に当たった場合です。後者はトークンを渡す#861が対処した問題で、前者は#861が生んだ問題でした。
発生条件は次の2点です。
- GHES(または同種のGitHub Enterprise環境)上でワークフローを実行している
- claude-code-actionが、
setup-bunへ無条件にトークンを渡すv1.0.42以降の版である
uda832は、GitHub Enterprise(GHE)でも同じ401が出ると報告しました。actions/create-github-app-tokenのログにはgithub-api-url: https://api.{組織のドメイン}.ghe.com/と出ており、ワークフローが取得したトークン自体はGHE向けの正しいものでした。
原因 — setup-bunが常にgithub.comへリクエストしていた
原因はsetup-bun側のバージョン解決処理です。issue発生当時に使われていたsetup-bun@v2.1.2は、次のコードでした。
async function getSemverDownloadUrl(options: Input): Promise<string> {
const res = (await (
await request("https://api.github.com/repos/oven-sh/bun/git/refs/tags", {
headers: options.token
? { "Authorization": `Bearer ${options.token}` }
: {},
})
).json()) as { ref: string }[];
// …bun-versionが1.3.6のような完全なバージョンでも、必ずapi.github.comのタグ一覧を取りに行きます。トークンがあればそのままBearerヘッダーに載せます。claude-code-actionが渡すのはGHESインスタンス向けのトークンなので、github.com側では無効で、401になります。
実はsetup-bun自身も、同じ種類の401を起こしていました。2026年1月16日にGHES利用者が、v2.1.1以降で401になるとsetup-bunのissue #156で報告しています。原因は、既定のgithub.tokenをGHESでもgithub.comへ送っていたことでした。そのissueの再現例はbun-version: 1.2.13の完全指定で、完全なバージョンでもタグ一覧を取りに行く実装だったことがここからも分かります。同日のv2.1.2(setup-bun #157)で、既定トークンはpublicなgithub.comのときだけ使う形に直っています。その配慮は、呼び出し側がtokenを明示した場合には効きません。claude-code-actionのtoken: ${{ inputs.github_token || github.token }}は明示的な指定にあたるため、#861で渡したトークンはそのままgithub.comへ送られました。
修正案は3件とも未マージ
issueのコメントでは、claude-code-action側を直す案が3件挙がっています。いずれもマージされていません。
| PR | 作者 | 内容 | 状態 |
|---|---|---|---|
| #901 | 作者peloyeje | 内容github.com向けトークンをgithub_dotcom_token入力として分離 | 状態2026年2月9日にclosed(未マージ) |
| #913 | 作者peloyeje | 内容GHESでのBunインストール手順をFAQに追記(docsのみ) | 状態open |
| #1001 | 作者luka5 | 内容setup-bunと同じ「public github.com以外では既定トークンを使わない」判定に変更 | 状態open |
#913の説明文は、自分が#861と#901に取って代わると書いています。内容は、GHESでは自前でBunを入れ、実行ファイルをpath_to_bun_executableで渡すという案内です。dr-goo(2026年3月17日)は「実質的な修正は#913だが、docs系PRのマージが遅れている」とコメントしています。#1001は、GHESで動作確認済みと説明しています。3件のうち#901は入力を足す案、#1001は判定の側を直す案、#913は利用者側の設定で避ける案です。
現在のmainで401が起きない理由
issueは開いたままでも、現在のaction.ymlでは別の経路でこの401が止まっています。時系列で追うと次のとおりです。
401が止まるまでの経緯
- 2026年2月1日#861がマージされ、v1.0.42に入る
v1.0.42のリリースは2026年2月3日。
setup-bunにトークンを渡す変更です。ピン留め先はsetup-bunv2.1.2、bun-versionは1.3.6。 - 2026年2月5日setup-bun #161がマージされる
「perf: avoid unnecessary api calls」。setup-bunのissue #159を閉じる変更で、完全なバージョンならタグ一覧の取得を省く分岐が入ります。
- 2026年3月4日setup-bun v2.1.3がリリースされる
#161を含む最初のリリース。ただしclaude-code-actionのピン留めはv2.1.2のままです。
- 2026年4月20日#1238がマージされる
Node.js 24対応のため、ピン留めをv2.2.0(2026年3月14日リリース)に更新。ここで#161の分岐が初めて届きます。
- 2026年5月14日#1312がマージされる
bun-versionが1.3.14に更新されます。
api.github.comを呼ばなくなる分岐は、次のコードです。v2.1.3とv2.2.0にあり、v2.1.2にはありません。
async function getSemverDownloadUrl(options: Input): Promise<string> {
const { version, os, arch, avx2, profile } = options;
let tag: string | undefined;
if (validateStrict(version)) {
tag = `bun-v${version}`;
}
if (!tag) {
// ここで初めてrefs/tagsへリクエストするbun-versionが1.3.14のような完全なバージョンなら、validateStrict()がtrueを返します。タグを直接組み立てるので、トークンの有無にかかわらずrefs/tagsへのリクエストが発生せず、401も起きません。
#1238はissue #896への対応ではありません。401を止めた分岐は、その手前のv2.1.3に入った性能改善に由来します。mainのaction.ymlは今もtoken: ${{ inputs.github_token || github.token }}でsetup-bunにトークンを渡しています。渡していても、APIを呼ばなければ使われません。
つまり、issueの状態だけを見て「未解決」と判断すると、現在の@v1では実質的に起きない事象を過大に見積もります。なおaction.ymlではbun-versionがハードコードで、ワークフロー側の入力にはありません。
古い版に固定したままGHESで動かす回避策
トークンを渡すと401、渡さないと403になる。固定版のGHESには、この板挟みがありました。#913の説明文によると、GHESでは未認証のgithub.com向けリクエストがレート制限の403で落ちやすいとのことです。トークンを渡す#861は、その403を401に置き換えた形でした。
#913がdocs/faq.mdに足した案内は、Bunを自分で用意してpath_to_bun_executableで渡す方法です。curlで入れる例は次のとおりです。
steps:
- name: Install Bun
run: |
curl -fsSL https://bun.sh/install | bash
echo "$HOME/.bun/bin" >> $GITHUB_PATH
- uses: anthropics/claude-code-action@v1
with:
path_to_bun_executable: "$HOME/.bun/bin/bun"with:の値はシェルで展開されないため、実際の運用では$HOMEを使わず、bunの絶対パスを書く方が確実です。この例ではInstall Bunステップで$HOME/.bun/binがPATHに入っているため動作します。
同じFAQには、oven-sh/setup-bunにgithub.comのpublic_repo権限付きPATを渡す例も載っています。ただしPATを使う案は、GHESの運用でgithub.com用の資格情報を別に持つことになります。
action.ymlでは、path_to_bun_executableを指定したときの説明が「通常は不要で、デバッグや特殊な環境向け」となっています。さらに互換性のないBunを渡すと動かない場合がある、との警告つきです。別途入れるBunの版は、action.ymlが組み込みで使うbun-version(現在は1.3.14)に合わせておくと、互換性の問題を避けやすくなります。
影響が残る条件
上の説明は、setup-bun v2.1.3以降とbun-versionの完全指定がそろった場合のものです。次のケースは別に考える必要があります。
- 古い版に固定している場合:
@v1.0.42のように#1238より前へピン留めしていると、setup-bunもv2.1.2のままで401が再現します。@v1は浮動タグで、v1.0.42より新しいコミットを指しており、#1238を含みます path_to_bun_executableを指定している場合:setup-bunステップ自体がif: inputs.path_to_bun_executable == ''でスキップされるため、この経路に当たりません- forkやカスタムビルドを使っている場合:
bun-versionを変数化したり、独自にsetup-bunを^1.3.0のような範囲指定で呼んだりすると、validateStrict()が偽になり、再びタグ一覧を取りに行きます
Bunのインストールは、Claude Code本体を起動する前の共通ステップです。メンション対応・auto-triage・自動コードレビューなど、claude-code-actionを使うワークフロー全種が同じsetup-bunステップを通ります。
自分のワークフローが当たっていたか調べる
影響範囲の確認手順
- 1
usesの行を見る
.github/workflows/*.ymlのanthropics/claude-code-actionの行が、@v1のような浮動タグか、@v1.0.42前後の固定版かを見ます。コミットSHAで固定している場合は、#1238のマージコミット4c682d8より前かどうかを、GitHubのcompare画面で調べられます。 - 2
過去の実行ログを探す
GHESのActionsタブで、該当ワークフローの
setup-bunステップに401が残っていないかをさかのぼります。 - 3
固定版なら上げる
@v1か、#1238以降のコミットに上げれば解消します。固定を外せない事情があれば、path_to_bun_executableでBunの自動インストールを避けられます。
GHES上のClaude Code導入全般はGitHub Enterprise ServerでClaude Codeを使うにあります。
セルフホストランナーでも、この401は接続性の問題ではありません。ログのとおりapi.github.comは401の応答を返しており、到達はできています。原因はトークンの発行元がGHESであることなので、ファイアウォールを見直しても変わりません。
まとめ
issueが開いたままでも、現在の@v1では完全指定のbun-versionとsetup-bun v2.1.3以降の分岐によりrefs/tagsが呼ばれず、401は起きません。影響が残るのは、#1238より前のコミットに固定している環境と、forkでbun-versionを範囲指定にした場合です。claude-code-actionの他の既知の不具合は、tsconfig.jsonクラッシュやBedrock認証が壊れた不具合で扱っています。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- github.com/anthropics/claude-code-action/issues/896
- github.com/anthropics/claude-code-action/pull/861
- github.com/anthropics/claude-code-action/pull/1238
- github.com/anthropics/claude-code-action/pull/901
- github.com/anthropics/claude-code-action/pull/913
- github.com/anthropics/claude-code-action/pull/1001
- github.com/anthropics/claude-code-action/pull/1312
- github.com/oven-sh/setup-bun/pull/157
- github.com/oven-sh/setup-bun/pull/161
- github.com/oven-sh/setup-bun/releases/tag/v2.1.3