--- title: "Using the Latest Bun on Cloudflare Pages" tags: ['Bun', 'Cloudflare Pages'] published: 2026-07-06 21:56:42 updated: 2026-07-06 21:56:42 excerpt: "Use the current Bun release on Cloudflare Pages by skipping automatic dependency installation, installing Bun through npm, and putting npm's global binary directory first in PATH." --- > This file is the raw Markdown source of an m.ac post; the canonical version lives at https://m.ac/latest-bun-cloudflare-pages/ > The full index of posts and pages is at https://m.ac/llms.txt — read the index first before crawling further. Cloudflare Pages supports Bun, at least on paper. The [Pages build image documentation](https://developers.cloudflare.com/pages/configuration/build-image/#languages-and-runtime) lists Bun in the supported runtime table, lets you override it with `BUN_VERSION`, and says the v3 build image defaults to Bun `1.2.15`. That sounds simple until you ask for `BUN_VERSION=latest` and your deployment fails before your app even gets a chance to embarrass itself. As of July 6, 2026, the latest Bun release is `1.3.14`, while Cloudflare Pages still defaults to Bun `1.2.15`. After a few rounds of testing, the most reliable fix I found is to skip Cloudflare's automatic dependency install, install Bun through npm with scripts enabled, and force the build shell to use npm's global binary path before Cloudflare's preinstalled Bun. ## 1. What goes wrong with BUN_VERSION=latest Cloudflare's documented path is to set `BUN_VERSION` in your Pages project. For the default preinstalled version, that can be fine. For `latest` or any other specific version, it can fail during Bun installation with a `403` from the installer path: ```log 2026-07-06T01:18:13.088163Z Installing bun latest 2026-07-06T01:18:13.34936Z Plugin bun's list-all callback script failed with output: 2026-07-06T01:18:13.351082Z curl: (22) The requested URL returned error: 403 2026-07-06T01:18:13.353396Z 2026-07-06T01:18:13.365851Z bun is already installed 2026-07-06T01:18:13.61882Z Plugin bun's list-all callback script failed with output: 2026-07-06T01:18:13.619964Z curl: (22) The requested URL returned error: 403 2026-07-06T01:18:13.622207Z 2026-07-06T01:18:13.63001Z Error: Exit with error code: 1 2026-07-06T01:18:13.630373Z at ChildProcess. (/snapshot/dist/run-build.js) 2026-07-06T01:18:13.630738Z at Object.onceWrapper (node:events:652:26) 2026-07-06T01:18:13.630897Z at ChildProcess.emit (node:events:537:28) 2026-07-06T01:18:13.63146Z at ChildProcess._handle.onexit (node:internal/child_process:291:12) 2026-07-06T01:18:13.638586Z Failed: build command exited with code: 1 2026-07-06T01:18:14.841415Z Failed: error occurred while running build command ``` This is not a brand-new paper cut. Related reports have been around for years, including [oven-sh/setup-bun#70](https://github.com/oven-sh/setup-bun/issues/70) and [oven-sh/bun#6305](https://github.com/oven-sh/bun/issues/6305). The short version: the install flow can trip over a remote download or rate limit problem, and Cloudflare Pages treats that as a failed build. Fair enough, but not very helpful when all you wanted was `bun install`. The funny part is that this is not Cloudflare rate-limiting Bun. It is Bun's own download side saying no, while [bun.sh](https://bun.sh/) and [bun.com](https://bun.com/) currently return `server: cloudflare`. Infrastructure irony, served with a `403`. I also checked [the current installer script](https://bun.sh/install). On Linux, it is refreshingly boring: detect the platform and CPU, pick a target such as `linux-x64`, `linux-x64-baseline`, `linux-aarch64`, or a musl build for Alpine, then download `https://github.com/oven-sh/bun/releases/latest/download/bun-$target.zip`, unzip it into `$BUN_INSTALL/bin` or `~/.bun/bin`, and mark the binary executable. If `bun` is not already on `PATH`, it writes the usual `BUN_INSTALL` and `PATH` lines into the user's shell config when it can, or prints the commands to add manually. There is no package index, dependency solver, or anything especially magical here. It is mostly a small shell script pointing at GitHub Release assets, which makes the rate limit feel even stranger. ## 2. Why npm install -g bun alone is not enough There is a common workaround: skip automatic dependency installation and run Bun yourself. For example, [dt.in.th documented](https://dt.in.th/BunCloudflarePages) this pattern: ```bash npm install -g bun && bun install && bun run build ``` That gets close, but in my Cloudflare Pages tests it still used Cloudflare's older preinstalled Bun. The build log told on it: ```log 2026-07-06T19:40:16.361085Z Executing user command: npm install -g bun && bun install && bun run build 2026-07-06T19:40:33.293457Z 2026-07-06T19:40:33.30093Z added 5 packages in 16s 2026-07-06T19:40:33.301321Z npm warn allow-scripts 1 package has install scripts not yet covered by allowScripts: 2026-07-06T19:40:33.301456Z npm warn allow-scripts bun@1.3.14 (postinstall: node install.js) 2026-07-06T19:40:33.301535Z npm warn allow-scripts 2026-07-06T19:40:33.301612Z npm warn allow-scripts Run `npm approve-scripts --allow-scripts-pending` to review, or `npm approve-scripts ` to allow. 2026-07-06T19:40:33.966013Z Reshimming asdf nodejs... 2026-07-06T19:40:43.03495Z bun install v1.2.15 (df017990) ``` Two things happened there: 1. npm installed the `bun` package, but its install script needed to be allowed. 2. The shell still resolved `bun` to Cloudflare's preinstalled/asdf-shimmed Bun before the npm-installed binary. The result is the worst kind of failure: it looks like you installed the new Bun, then the build quietly uses the old one. Very considerate. Also very wrong. ## 3. The working Cloudflare Pages setup First, disable automatic dependency installation so Cloudflare Pages does not run its own package manager step before your command. In the Cloudflare Dashboard: 1. Go to **Build > Compute > Workers & Pages** 2. Open your Pages project 3. Go to **Settings > Variables and secrets** 4. Add this build variable: Type: `Text` Variable name: ```text SKIP_DEPENDENCY_INSTALL ``` Value: ```text true ``` or ```text 1 ``` Cloudflare documents this variable in its [build image guide](https://developers.cloudflare.com/workers/ci-cd/builds/build-image/#skip-dependency-install): it disables automatic dependency installation so you can run a custom install command. Then set your Pages build command to this: ```bash npm install -g --allow-scripts=bun bun && export PATH="$(npm prefix -g)/bin:$PATH" && bun --version && bun install && bun run build ``` Screenshot: ![Cloudflare Pages build settings with SKIP_DEPENDENCY_INSTALL and a custom Bun build command](https://macdn.net/2026/07/06/m8h8q/image.webp) Here is what each part does: 1. `npm install -g --allow-scripts=bun bun` Installs Bun from npm and allows Bun's install script to run. Without that script, you can end up with the wrapper package but not the native Bun binary you actually need. 2. `export PATH="$(npm prefix -g)/bin:$PATH"` Puts npm's global binary directory at the front of `PATH`. This is the important bit. It makes the next `bun` command resolve to the npm-installed Bun instead of Cloudflare's default Bun `1.2.15`. 3. `bun --version` Prints the Bun version in the build log. This is not decoration. It is the smoke alarm. If this does not print the version you expect, stop reading the rest of the log like it owes you money and fix the PATH first. 4. `bun install && bun run build` Installs dependencies and runs your normal build with the Bun binary you just verified. ## 4. What a good build log looks like With the command above, the build finally used Bun `1.3.14`: ```log 2026-07-06T19:57:20.330572Z SKIP_DEPENDENCY_INSTALL is present in environment. Skipping automatic dependency installation. 2026-07-06T19:57:20.330827Z Executing user command: npm install -g --allow-scripts=bun bun && export PATH="$(npm prefix -g)/bin:$PATH" && bun --version && bun install && bun run build 2026-07-06T19:57:26.270869Z added 5 packages in 5s 2026-07-06T19:57:26.853104Z Reshimming asdf nodejs... 2026-07-06T19:57:29.865184Z 1.3.14 2026-07-06T19:57:29.870732Z bun install v1.3.14 (0d9b296a) 2026-07-06T19:58:07.304997Z Success! Uploaded 38 files (2604 already uploaded) (1.85 sec) 2026-07-06T19:58:12.958621Z Success: Assets published! 2026-07-06T19:58:13.849805Z Success: Your site was deployed! ``` The key lines are: ```log 1.3.14 bun install v1.3.14 (0d9b296a) ``` That proves both `bun --version` and `bun install` are using the same current Bun binary. ## 5. Should you use latest or pin a version? For a personal site or a small project, installing the latest Bun during the Pages build may be convenient. You get current fixes without editing the Cloudflare project every time Bun ships. For production builds where repeatability matters, pin the npm package instead: ```bash npm install -g --allow-scripts=bun bun@1.3.14 && export PATH="$(npm prefix -g)/bin:$PATH" && bun --version && bun install && bun run build ``` That keeps the same PATH fix, but removes surprise upgrades from the equation. Surprise upgrades are fun in exactly one place: other people's staging environments. ## 6. Final checklist Use this setup when you want Cloudflare Pages to build with the current Bun instead of the preinstalled default: 1. Add `SKIP_DEPENDENCY_INSTALL=true` in Pages variables and secrets. 2. Use this build command: ```bash npm install -g --allow-scripts=bun bun && export PATH="$(npm prefix -g)/bin:$PATH" && bun --version && bun install && bun run build ``` 3. Check the build log for the expected version after `bun --version`. 4. Check that `bun install` reports the same version. If Bun or Cloudflare fixes the issue later, this workaround can become shorter. Bun can fix the rate limit behavior on its own download side. Cloudflare can also avoid Bun's installer script for a managed build runtime and fetch the versioned or latest GitHub Release asset directly. Neither option requires a new theory of computing. Until then, the build command above gives you the latest Bun without asking Cloudflare's preinstalled runtime to kindly stop standing in the doorway.