oven-sh/bun · error · Error

${options.label ?? cmd[0]}: ${r.error.message}

Error message

${options.label ?? cmd[0]}: ${r.error.message}

What it means

The runCommand helper in scripts/orderfile/generate.ts wraps spawnSync and throws when r.error is set — meaning the command never ran successfully as a process: cmd[0] was not found (ENOENT) or options.timeout expired (spawnSync reports ETIMEDOUT). The label (or cmd[0]) prefixes the underlying error message so you know which invocation failed.

Source

Thrown at scripts/orderfile/generate.ts:112

/**
 * Runs a command to completion, throwing if it could not be spawned. Exported so
 * a test can drive it under node: bun's spawnSync delivers `input` whatever stdin
 * is, so the wiring below only ever breaks on CI, which builds under node.
 */
export function runCommand(cmd: string[], options: RunOptions = {}) {
  const r = spawnSync(cmd[0]!, cmd.slice(1), {
    env: { ...process.env, ...options.env },
    cwd: options.cwd,
    input: options.input,
    timeout: options.timeout,
    // Only a pipe carries `input`: node drops it when stdin is "ignore", and
    // then an interactive workload reads nothing and waits forever for a line.
    stdio: [options.input === undefined ? "ignore" : "pipe", "pipe", "pipe"],
    maxBuffer: 1 << 29, // nm prints ~10 MB of symbols
  });
  // A timeout arrives here too: spawnSync reports it as an ETIMEDOUT error.
  if (r.error) throw new Error(`${options.label ?? cmd[0]}: ${r.error.message}`);
  return r;
}

export interface GenerateOptions {
  /** Build directory holding the unstripped binary. */
  buildDir: string;
  /** Unstripped binary to trace. Defaults to `bun-profile`; an assertions build names it differently. */
  exeName?: string;
  /** Where to write the order file. Defaults to `<buildDir>/linker.order`. */
  outPath?: string;
  /** Fail if fewer than this many functions were traced. */
  minFunctions?: number;
  /** Print per-workload progress. */
  verbose?: boolean;
}

/**
 * Linker-visible function names, by address. Multiple names can share one

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Read the label before the colon to identify which command failed to spawn
  2. Install the missing tool: Xcode Command Line Tools (`xcode-select --install`) on macOS, binutils + a C compiler on Linux
  3. Check CC and NM environment overrides point at real executables (`command -v "$CC"`)
  4. If the message says ETIMEDOUT, raise the relevant timeout or investigate why the workload hung

Example fix

# before (missing toolchain on fresh macOS)
$ bun scripts/orderfile/generate.ts
Error: nm: spawnSync nm ENOENT

# after
$ xcode-select --install
$ bun scripts/orderfile/generate.ts
Defensive patterns

Strategy: try-catch

Validate before calling

import { spawnSync } from "node:child_process";

const resolvable = (bin) => spawnSync("which", [bin]).status === 0;
for (const bin of [process.env.NM || "nm", process.env.CC || "cc"].filter(Boolean)) {
  if (!resolvable(bin)) throw new Error(`${bin} not found on PATH — install the toolchain first`);
}

Type guard

function isSpawnError(r: { error?: Error }): r is { error: Error } {
  return r.error !== undefined;
}

Try / catch

try {
  const r = runCommand([nm, bunProfile]);
} catch (err) {
  const msg = String(err);
  if (msg.includes("ENOENT")) throw new Error(`Missing toolchain binary — install it: ${msg}`);
  if (msg.includes("ETIMEDOUT")) throw new Error(`Command timed out — raise options.timeout: ${msg}`);
  throw err;
}

Prevention

When it happens

Trigger: Running the orderfile generator without nm or a C compiler on PATH; CC or NM env vars pointing at nonexistent executables; a workload exceeding WORKLOAD_TIMEOUT_MS, which surfaces here as an ETIMEDOUT error rather than a status code.

Common situations: Fresh macOS without Xcode Command Line Tools; slim Linux containers without binutils/build-essential; CI images missing the toolchain; stale CC overrides in the environment.

Related errors


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