Cloudflare Workers Builds のビルド変数は、ダッシュボードから設定しても非本番ブランチには入らない
Bun 1.4 で bun.lock の形式が 2 に上がり、Cloudflare Workers Builds の非本番ブランチのビルドだけが止まりました。ビルド環境の Bun が古いことが原因でしたが、ダッシュボードで BUN_VERSION を設定しても直りません。ビルド設定が本番とプレビューの 2 つのトリガーに分かれて保存されている仕組みと、REST API での修正手順を紹介します。
目次
Cloudflare Workers Builds は、GitHub のリポジトリと連携させておくと、push のたびにビルドとデプロイを実行してくれます。ビルドに使う変数は、ダッシュボードの「設定 > ビルド > 変数とシークレット」から追加できます。私はここに BUN_VERSION を入れて、ビルド環境の Bun のバージョンを固定していました。
Bun を 1.4 系へ上げたときも、この欄の値を書き換えました。main へマージしたビルドは成功します。ところが main 以外のブランチへ push したビルドだけは、依存関係のインストールで止まったままでした。同じリポジトリ、同じ bun.lock、同じビルドコマンドで、違いはブランチだけです。
原因は 2 つ重なっていました。Bun 1.4 でロックファイルの形式が変わったこと、そして Workers Builds のビルド設定が本番用とプレビュー用の 2 つに分かれて保存されていることです。この記事では、失敗の切り分けから REST API での修正までを書きます。
NOTE
2026 年 9 月 6 日に確認した内容です。Cloudflare のビルドイメージの既定は Bun 1.2.15 / Node.js 24.18.0、リポジトリ側の Bun は 1.4.0 です。ビルドイメージの既定バージョンは今後変わる可能性があります。
非本番ブランチだけで起きた失敗
失敗したビルドのログです。依存関係のインストールに入ってすぐ止まっています。
Detected the following tools from environment: bun@1.2.15, nodejs@24.18.0
Installing project dependencies: bun install --frozen-lockfile
bun install v1.2.15 (df017990)
2 | "lockfileVersion": 2,
^
error: Unknown lockfile version
at bun.lock:2:22
UnknownLockfileVersion: failed to parse lockfile: 'bun.lock'
warn: Ignoring lockfile
error: lockfile had changes, but lockfile is frozen
Failed: error occurred while installing tools or dependenciesbun.lock には形式の番号があり、Bun のリファレンスでは lockfileVersion の型が 0 | 1 | 2 です。Unknown lockfile version は、そこに書かれた番号をその Bun が知らないときのエラーでした。ログのロックファイルは 2、読もうとした Bun は 1.2.15 です。
もう 1 か所、Detected the following tools from environment: の行には、そのビルドで使われる Bun と Node.js のバージョンが出ます。ここが bun@1.2.15 です。main へ push したときのビルドで同じ行を見ると bun@1.4.0 でした。ブランチによって、ビルド環境に入る Bun が違っていたことになります。
bun.lock の形式が 2 に上がった境目
Bun 1.4.0 は 2026 年 8 月 19 日にリリースされました。破壊的変更をまとめた oven-sh/bun#28792 に、次の項目があります。
bun.lockdefaultlockfileVersionis now2(#31539). (中略)Existing v0/v1 lockfiles continue to load. Older Bun versions cannot read v2 lockfiles.
新しい Bun は古い形式のロックファイルを読めますが、古い Bun は新しい形式を読めません。互換性は片方向です。
境目のバージョンを手元で確かめました。依存を is-number@7.0.0 だけにした同じ package.json を 2 つのディレクトリに置き、片方を Bun 1.3.14、もう片方を Bun 1.4.0 でインストールします。生成された bun.lock の 2 行目を見比べます。
bunx bun@1.3.14 install --cwd probe/bun-1.3.14
bunx bun@1.4.0 install --cwd probe/bun-1.4.0
head -2 probe/bun-1.3.14/bun.lock probe/bun-1.4.0/bun.lock==> probe/bun-1.3.14/bun.lock <==
{
"lockfileVersion": 1,
==> probe/bun-1.4.0/bun.lock <==
{
"lockfileVersion": 2,1.3 系の最終版である 1.3.14 はまだ 1 を書き、2 を書き始めるのは 1.4 からでした。同じ結果は vercel/turborepo の Discussion #13126 でも報告されています。
Cloudflare のビルドログと同じエラーは、Cloudflare を経由しなくても手元で出せます。形式 2 の bun.lock と、それに対応する package.json を repro/ へ置き、古い Bun でインストールを実行しました。
bunx bun@1.2.15 install --cwd repro --frozen-lockfilebun install v1.2.15 (df017990)
2 | "lockfileVersion": 2,
^
error: Unknown lockfile version
at bun.lock:2:22
UnknownLockfileVersion: failed to parse lockfile: 'bun.lock'
warn: Ignoring lockfile
error: lockfile had changes, but lockfile is frozenビルドログと 1 行も違いません。失敗の直接の原因は、形式 2 のロックファイルを Bun 1.2.15 が読めないことでした。
bun.lock の形式を決めるのは、それを書き出した Bun のバージョンです。手元の Bun を 1.4 系へ上げて bun install を一度実行すると、ロックファイルは形式 2 に書き換わり、その差分がコミットに乗ります。リポジトリが形式 2 へ移った時点で、古い Bun でインストールする環境は止まります。
ビルド環境の Bun のバージョンを決める場所
Workers Builds のビルドイメージに最初から入っている Bun は 1.2.15 です。Build image のドキュメントに、ツールごとの既定バージョンと、それを上書きする方法が載っています。
上書きの手段は 2 通りあります。ビルド変数で指定するか、決められた名前のファイルをリポジトリに置くかです。ファイル名の一覧が載っているのはランタイムの表だけで、Node.js には .nvmrc と .node-version、Python には .python-version と runtime.txt が並んでいます。Bun があるのはもう一方の表で、そちらにはファイル名の列そのものがありません。Bun に用意されていた手段は、ビルド変数 BUN_VERSION だけでした。
リポジトリ側から Bun を指定したいという要望は Cloudflare Community に出ていますが、この記事を書いている時点で .bun-version は未対応です。package.json の packageManager フィールドを Workers Builds が読むかどうかは、ドキュメントに記載がなく、私も試していません。
このリポジトリでは mise.toml に Bun のバージョンを書いて固定していますが、Cloudflare のビルド環境はこのファイルを見ません。ビルド環境を 1.4 系にするには BUN_VERSION を使うしかない、ということになります。そしてその BUN_VERSION は、ダッシュボードから設定済みでした。main のビルドが bun@1.4.0 で動いていたのも、この値が設定されていたからです。それでも非本番ブランチだけは 1.2.15 のままでした。
ビルド変数が保存される単位
Workers Builds API reference に、次のように書かれています。
Each Worker has up to two triggers: one for production (runs on your production branch) and one for preview (runs on all other branches).
Workers Builds がビルド設定を持つ単位は「トリガー」です。1 つの Worker につきトリガーは最大 2 つあり、本番ブランチを対象にするものと、それ以外のすべてのブランチを対象にするものに分かれます。
分かれているのはブランチの条件だけではありません。ビルドコマンド、デプロイコマンド、そしてビルド変数も、トリガーごとに独立して持ちます。同じドキュメントの environment_variables の説明はこうです。
environment_variables— Build-time variables specific to this trigger
ビルド変数が紐づく先は、Worker ではなくトリガーでした。一方、ダッシュボードの「変数とシークレット」の欄は 1 つしかありません。ビルド設定のページに 1 つだけ置かれた欄を見て、私はそこに入れた値がこの Worker のビルド全体に届くものだと思っていました。実際に保存されていたのは、本番トリガーの分だけです。
REST API で 2 つのトリガーを取得して並べると、こうなっていました。
| トリガー | branch_includes |
branch_excludes |
ビルド変数 |
|---|---|---|---|
| 本番 | ["main"] |
[] |
BUN_VERSION: 1.4.0 |
| プレビュー | ["*"] |
["main"] |
なし |
プレビュートリガーには何も入っていません。ここが空だと、ビルド環境の Bun は既定の 1.2.15 になります。main へのマージが成功し続け、非本番ブランチだけが止まっていた理由がこれです。
ロックファイルの形式が 1 だった間は、Bun 1.2.15 でも読めていました。プレビュートリガーが空のままでもビルドは成功していたので、この食い違いには気づきませんでした。
ダッシュボードには、プレビュートリガーの変数を表示する場所も、編集する場所もありません。設定されているかどうかを画面から確かめられず、ビルドログの Detected the following tools from environment: の行を見て初めて分かる状態でした。
プレビュートリガーに BUN_VERSION を設定する
ダッシュボードから操作できないので、REST API を使います。
まず、「Workers Builds Configuration: 編集」の権限を付けた API トークンを作ります。Worker のタグを API で調べるなら「Workers Scripts: 読み取り」も必要です。Builds API reference にあるとおり、この API が受け付けるのはユーザー単位のトークンだけで、アカウント単位のトークンには Invalid token が返却されます。
IMPORTANT
wrangler login で作られる OAuth トークンでは、Workers Builds の API は使えません。wrangler whoami が使うトークンでトリガー一覧を取得すると {"code": 10000, "message": "Authentication error"} が返却されます。ダッシュボードの「API トークン」から別に作る必要があります。
デプロイ用に既に持っているトークンがあっても、Workers Builds 構成の権限が付いていなければ同じエラーになります。私も専用のトークンを作り、設定を終えてから削除しました。
トークンとアカウント ID を環境変数に入れ、Worker のタグを取得します。my-worker の部分は自分の Worker 名に置き換えてください。
export CF_API_TOKEN='<作成したトークン>'
export CF_ACCOUNT_ID='<アカウント ID>'
TAG=$(curl -s "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/workers/scripts" \
-H "Authorization: Bearer $CF_API_TOKEN" \
| jq -r '.result[] | select(.id=="my-worker") | .tag')このタグを使って、トリガーの一覧を取得します。
curl -s "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/builds/workers/$TAG/triggers" \
-H "Authorization: Bearer $CF_API_TOKEN" \
| jq '.result[] | {trigger_uuid, trigger_name, branch_includes, branch_excludes, build_command, deploy_command}'branch_includes が ["*"] で branch_excludes が ["main"] になっているほうがプレビュートリガーです。その trigger_uuid を控えます。
この一覧の応答には、設定済みのビルド変数が含まれません。値を読むには、トリガーごとの別のエンドポイントを呼びます。
export PREVIEW_UUID='<プレビュートリガーの UUID>'
curl -s "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/builds/triggers/$PREVIEW_UUID/environment_variables" \
-H "Authorization: Bearer $CF_API_TOKEN"私の場合、プレビュートリガーが返したのは {"result":{},"success":true,...} です。本番トリガーの UUID で同じことをすると、BUN_VERSION が入っていました。この 2 つを並べれば、ダッシュボードで保存した値が片方にしか設定されていないことが分かります。
設定は同じエンドポイントへの PATCH です。
curl -s "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/builds/triggers/$PREVIEW_UUID/environment_variables" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-X PATCH \
--data '{"BUN_VERSION":{"value":"1.4.0","is_secret":false}}'"success": true と、設定した変数の created_on が返ってきます。
設定後のビルド
空のコミットを作った検証用ブランチを push して、ビルドを実行しました。
Detected the following tools from environment: bun@1.4.0, nodejs@24.18.0
Installing bun 1.4.0
Installing project dependencies: bun install --frozen-lockfile
bun install v1.4.0 (34cbb9a40)
...
Success: Deploy command completed
✨ Success! Build completed.1 行目が bun@1.4.0 に変わり、Installing bun 1.4.0 の行が増えました。既定と違うバージョンを指定したため、ビルド環境が Bun を入れ直しています。
Workers Builds は、ビルド 1 件ごとの記録にその時点のビルド変数を保存します。修正の前後を並べると、変わったのは変数だけです。
| ブランチ | 結果 | 記録された変数 | 検出された Bun |
|---|---|---|---|
| 修正前の非本番ブランチ | fail | {} |
1.2.15 |
| 修正後の非本番ブランチ | success | BUN_VERSION: 1.4.0 |
1.4.0 |
まとめ
- Bun 1.4.0 から
bun.lockのlockfileVersionが 1 から 2 に上がる。1.3 系の最終版である 1.3.14 はまだ 1 を書く - 形式 2 のロックファイルを古い Bun で読ませると
Unknown lockfile versionで止まる。bunx bun@1.2.15 install --frozen-lockfileで手元でも再現できる - Cloudflare Workers Builds のビルドイメージには、Bun 1.2.15 が既定で入る。ドキュメントの表に Bun のバージョン指定ファイルの記載はなく、ビルド変数
BUN_VERSIONで指定する - Workers Builds のビルド設定は、本番用とプレビュー用の 2 つのトリガーに分かれて保存される。ビルド変数もトリガーごとに独立している
- ダッシュボードの「変数とシークレット」で保存した値は、本番トリガーにしか入らない。プレビュートリガーの変数は画面に表示されず、REST API でしか読み書きできない
- プレビュートリガーに
BUN_VERSIONが設定されているかは、ビルドログのDetected the following tools from environment:に出る Bun のバージョンで判断できる
参考
- Build image · Cloudflare Workers docs
- Build configuration · Cloudflare Workers docs
- Workers Builds API reference · Cloudflare Workers docs
BunLockFile.lockfileVersion· Bun reference- List of breaking changes for 1.4 · oven-sh/bun #28792
- Bun lockfile version: 2 (Bun 1.4.0/canary) · vercel/turborepo Discussion #13126
- Support .bun-version for build images · Cloudflare Community