oven-sh/bun · error · Error

Executable not found: bunx or npx

Error message

Executable not found: bunx or npx

What it means

In CI mode (the ci flag), machine.mjs bundles agent.mjs with esbuild via `bunx` or `npx` before shipping it to the machine. It probes PATH with which() for both executables and throws when neither is found, because the bundle step cannot run.

Source

Thrown at scripts/machine.mjs:1479

  }

  let bootstrapPath, agentPath, dockerfilePath;
  if (bootstrap) {
    bootstrapPath = resolve(
      import.meta.dirname,
      os === "windows"
        ? "bootstrap.ps1"
        : features?.includes("docker")
          ? "../.buildkite/Dockerfile-bootstrap.sh"
          : "bootstrap.sh",
    );
    if (!existsSync(bootstrapPath)) {
      throw new Error(`Script not found: ${bootstrapPath}`);
    }
    if (ci) {
      const npx = which("bunx") || which("npx");
      if (!npx) {
        throw new Error("Executable not found: bunx or npx");
      }
      const entryPath = resolve(import.meta.dirname, "agent.mjs");
      const tmpPath = mkdtempSync(join(tmpdir(), "agent-"));
      agentPath = join(tmpPath, "agent.mjs");
      await spawnSafe($`${npx} esbuild ${entryPath} --bundle --platform=node --format=esm --outfile=${agentPath}`);
    }

    if (features?.includes("docker")) {
      dockerfilePath = resolve(import.meta.dirname, "../.buildkite/Dockerfile");

      if (!existsSync(dockerfilePath)) {
        throw new Error(`Dockerfile not found: ${dockerfilePath}`);
      }
    }
  }

  // Use Packer for Windows Azure image builds — it handles VM creation,
  // bootstrap, sysprep, and gallery capture via WinRM (no Run Command hacks).

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Install Bun (provides bunx) or Node (provides npx) in the environment
  2. Fix PATH so the installed executable resolves (check `which bunx || which npx` in the same shell)
  3. Run without the ci flag when working locally — the esbuild bundling step is CI-only
Defensive patterns

Strategy: validation

Validate before calling

import { spawnSync } from "node:child_process";

const which = (bin) => spawnSync("which", [bin], { encoding: "utf8" }).status === 0;
const packer = which("bunx") || which("npx");
if (ci && !packer) {
  throw new Error("CI mode needs bunx or npx — install Bun or Node before running");
}

Prevention

When it happens

Trigger: Running with the ci flag inside an image that has neither Bun nor Node installed, or where npm's global bin directory is missing from PATH. The check runs only when ci is truthy and bootstrap is set.

Common situations: Minimal Docker/CI images (e.g. slim base) without Node/Bun; a CI job where PATH is reset by a wrapper; locally simulating CI in a clean shell.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/92349cf10a4a7a32. Report an issue: GitHub.