oven-sh/bun · error · BuildError
Cannot exec: build mode produced no executable
Error message
Cannot exec: build mode produced no executable
What it means
After a successful ninja build, scripts/build.ts execs the freshly linked binary with any trailing positional args. This BuildError fires when result.output.exe is undefined — the chosen mode builds artifacts rather than a host-runnable executable (the comment notes exe is bun-debug in debug, bun-profile in release).
Source
Thrown at scripts/build.ts:293
process.exit(ninja.status ?? 1);
}
if (args.execArgs.length === 0) {
// Closing line on success: when restat prunes most of the graph
// (local WebKit no-op shows `[1/555] build WebKit` then silence),
// it's not obvious ninja finished vs. stalled. This disambiguates.
// Targets named when explicit so it's clear what was actually built.
const what = args.ninjaTargets.length > 0 ? ` ${args.ninjaTargets.map(t => nameColor(t)).join(", ")}` : "";
status(`[build]${what} done`);
process.exit(0);
}
// Exec the built binary. result.output.exe is the linked (unstripped)
// binary — bun-debug for debug, bun-profile for release. That's the one
// you want for dev iteration (has symbols + assertions in debug).
const exe = result.output.exe;
if (exe === undefined) {
throw new BuildError("Cannot exec: build mode produced no executable", {
hint: `mode=${result.cfg.mode} builds artifacts, not a runnable binary. Drop the positional args or use --profile=debug.`,
});
}
const child = spawnSync(exe, args.execArgs, { stdio: "inherit" });
if (child.error) {
throw new BuildError(`Failed to exec ${exe}`, { cause: child.error });
}
// Signal death: re-raise so our parent sees the same signal (shells
// show "Segmentation fault" etc. based on this, not exit code).
if (child.signal) {
process.kill(process.pid, child.signal);
return;
}
process.exit(child.status ?? 0);
}
}
/**View on GitHub (pinned to 8c5296ac45)
Solutions
- Drop the positional/exec args — build only: bun run build windows-x64
- Or pick a runnable profile: add --profile=debug (produces bun-debug) before the exec args
- Check the mode named in the hint to confirm which profile produced artifacts
Example fix
# before — exec args on an artifact-only mode $ bun run build windows-x64 test/js/foo.test.ts BuildError: Cannot exec: build mode produced no executable # after — build only, no exec args $ bun run build windows-x64 # or run tests with a runnable profile $ bun bd test js/foo.test.ts
Defensive patterns
Strategy: validation
Validate before calling
// before build-then-exec, make sure the mode yields a host-runnable binary
const profile = process.argv.find(a => a.startsWith("--profile="))?.slice(9) ?? "debug";
const artifactOnly = /windows-(x64|arm64)/.test(profile); // cross-compile from non-Windows hosts
const hasExecArgs = process.argv.slice(2).some(a => !a.startsWith("-"));
if (hasExecArgs && artifactOnly) {
console.error("refusing: artifact-only profile cannot exec; remove trailing args");
process.exit(2);
} Prevention
- Keep build-only and build-then-exec commands in separate npm scripts
- Cross-compile profiles never exec — do not reuse `bd test ...` muscle memory on them
When it happens
Trigger: Passing exec args to an artifact-only mode — e.g. bun run build windows-x64 <args...> on a non-Windows host (cross-compile output cannot run here), or a target/profile whose output is objects or a library rather than the bun binary.
Common situations: Cross-compiling Windows builds from Linux/macOS and leaving trailing args on the command; using --target with positional exec args; copying a `bun bd test ...` invocation onto a cross-compile profile.
Related errors
- --${rawKey} requires a value
- Unknown config field: --${rawKey}
- Invalid boolean value: ${v}
- Usage: ./${scriptPath} [ssh|create-image|publish-image] [opt
- usage: bun src/codegen/generate-string-map.ts <input.string-
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/0ba5f3a6fc7914c2.
Report an issue: GitHub.