oven-sh/bun · error · Error
failed to build the pty runner with ${cc} ${pty.stderr}
Error message
failed to build the pty runner with ${cc}
${pty.stderr} What it means
Compiling ptyrun.c — the pseudo-terminal runner that executes interactive workloads under a real tty — failed, with compiler stderr appended. On Linux it additionally links -lutil for the pty APIs, so a missing util library is a platform-specific cause.
Source
Thrown at scripts/orderfile/generate.ts:211
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 ──────────────────────────────────────
const symbols = readSymbolTable(bunProfile);
const startsPath = join(scratch, "starts.bin");
writeStarts(
startsPath,
[...symbols.keys()].sort((a, b) => a - b),
);
// ── Representative workloads ──────────────────────────────────────────────
// Order matters: earlier workloads get the densest placement, so the plain
// runtime startup path comes first.
const fixtures = join(scratch, "fixtures");
mkdirSync(join(fixtures, "tests"), { recursive: true });
writeFileSync(
join(fixtures, "hello.ts"),
`const greet = (name: string): string => \`hi \${name}\`;\nconsole.log(greet("world"));\n`,
);View on GitHub (pinned to 8c5296ac45)
Solutions
- Read the appended stderr — it distinguishes a missing -lutil from a compile error
- Install/repair the C toolchain (build-essential / Xcode CLT) including libc dev pieces
- Set CC to a known-good compiler and re-run; scratch rebuilds are cheap
Defensive patterns
Strategy: try-catch
Validate before calling
import { spawnSync } from "node:child_process";
// Probe both compilations cheaply before the full run.
const probe = spawnSync(cc, ["-O2", "-o", "/tmp/ptyrun-probe", "ptyrun.c", ...(darwin ? [] : ["-lutil"])], { cwd: here });
if (probe.status !== 0) throw new Error(`pty runner would fail to build:\n${probe.stderr}`); Try / catch
try {
buildPtyRunner();
} catch (err) {
if (/failed to build the pty runner/.test(String(err))) {
console.error("Check -lutil availability on Linux and the C toolchain; stderr above names the cause");
}
throw err;
} Prevention
- Install libc development packages alongside the compiler in containers used for tracing
- Keep CC/NM overrides consistent within one environment
When it happens
Trigger: Same toolchain problems as the tracer build (no compiler, bad CC), plus on Linux a missing/unavailable libutil; on macOS an SDK mismatch affecting pty headers.
Common situations: Minimal containers lacking libc development files; broken CC overrides; toolchain half-installed so functrace.c compiled but ptyrun.c did not.
Related errors
- failed to build the tracer with ${cc} ${build.stderr}
- ${options.label ?? cmd[0]}: ${r.error.message}
- ${nm} failed on ${bunProfile} ${r.stderr}
- ${nm} reported no text symbols — is ${bunProfile} stripped?
- workload "${name}" wrote a truncated trace
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/135affca2e98c6f4.
Report an issue: GitHub.