oven-sh/bun · error · Error

${bunProfile} not found — build it first (bun run build:rele

Error message

${bunProfile} not found — build it first (bun run build:release)

What it means

The generator needs the unstripped binary at <buildDir>/bun-profile (or the exeName override) because its symbol table maps traced addresses back to function names; existsSync failed. The message tells you to build it first with `bun run build:release`.

Source

Thrown at scripts/orderfile/generate.ts:195

  for (let i = 0; i < count; i++) out[i] = Number(body[i]);
  return out;
}

export function generateOrderFile(options: GenerateOptions): { count: number; outPath: string } {
  const buildDir = resolve(options.buildDir);
  const outPath = resolve(options.outPath ?? join(buildDir, "linker.order"));
  const minFunctions = options.minFunctions ?? MIN_FUNCTIONS;
  const log = (message: string) => options.verbose && console.log(message);

  const darwin = process.platform === "darwin";
  if (process.platform !== "linux" && !(darwin && process.arch === "arm64")) {
    throw new Error("the order file tracer builds on linux x86-64/arm64 or macOS arm64");
  }

  // The unstripped binary: its symbol table is what maps addresses back to names.
  const bunProfile = join(buildDir, options.exeName ?? "bun-profile");
  if (!existsSync(bunProfile)) {
    throw new Error(`${bunProfile} not found — build it first (bun run build:release)`);
  }

  const scratch = mkdtempSync(join(tmpdir(), "bun-orderfile-"));
  try {
    // ── Build the tracer and the pty runner ───────────────────────────────────
    const tracer = join(scratch, darwin ? "functrace.dylib" : "functrace.so");
    const ptyrun = join(scratch, "ptyrun");
    const cc = process.env.CC || "cc";
    const build = runCommand(
      darwin
        ? [cc, "-O2", "-dynamiclib", "-fPIC", "-o", tracer, join(here, "functrace.c")]
        : [cc, "-O2", "-shared", "-fPIC", "-o", tracer, join(here, "functrace.c"), "-ldl", "-lpthread"],
    );
    if (build.status !== 0) throw new Error(`failed to build the tracer with ${cc}\n${build.stderr}`);
    const pty = runCommand([cc, "-O2", "-o", ptyrun, join(here, "ptyrun.c"), ...(darwin ? [] : ["-lutil"])]);
    if (pty.status !== 0) throw new Error(`failed to build the pty runner with ${cc}\n${pty.stderr}`);

    // ── Symbol table and function starts ──────────────────────────────────────

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Run `bun run build:release` first to produce the unstripped bun-profile
  2. Verify the path printed in the error and fix the buildDir you passed
  3. If your build names the binary differently, pass exeName so it resolves

Example fix

// before
generateOrderFile({ buildDir: "./build" }); // no bun-profile there yet

// after — build first, then generate (or name the binary explicitly)
// $ bun run build:release
generateOrderFile({ buildDir: "./build", exeName: "bun-profile" });
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from "node:fs";
import { join, resolve } from "node:path";

const buildDir = resolve(options.buildDir);
const bunProfile = join(buildDir, options.exeName ?? "bun-profile");
if (!existsSync(bunProfile)) {
  throw new Error(`${bunProfile} missing — run \`bun run build:release\` before generating the order file`);
}

Prevention

When it happens

Trigger: Running generate before any release build; passing a wrong buildDir; an assertions build that names the profiling binary differently so the default `bun-profile` misses.

Common situations: Fresh clones or cleaned build dirs; scripts invoked with a stale buildDir path; custom build configurations renaming the output binary.

Related errors


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