oven-sh/bun · error · Error
${nm} reported no text symbols — is ${bunProfile} stripped?
Error message
${nm} reported no text symbols — is ${bunProfile} stripped? What it means
nm succeeded but the filter /^([0-9a-f]+) ([tT]) (\S+)$/ matched zero defined text symbols in the output, so the address→name map is empty. As the message says, the canonical cause is a stripped binary — nm lists no local/global text symbols to match.
Source
Thrown at scripts/orderfile/generate.ts:152
* stripping — lld and ld take exactly what nm gave.
*/
function readSymbolTable(bunProfile: string): Map<number, string[]> {
// Bare `nm` with no GNU-only long options: the regex below is the
// defined-text-symbol filter, and nothing here depends on output order.
const nm = process.env.NM || "nm";
const r = runCommand([nm, bunProfile]);
if (r.status !== 0) throw new Error(`${nm} failed on ${bunProfile}\n${r.stderr}`);
const symbols = new Map<number, string[]>();
for (const line of r.stdout.toString().split("\n")) {
const m = /^([0-9a-f]+) ([tT]) (\S+)$/.exec(line);
if (!m) continue;
const address = parseInt(m[1]!, 16);
const names = symbols.get(address);
if (names) names.push(m[3]!);
else symbols.set(address, [m[3]!]);
}
if (symbols.size === 0) throw new Error(`${nm} reported no text symbols — is ${bunProfile} stripped?`);
return symbols;
}
/** Write function starts for functrace.c: u64 magic, version, count, addresses. */
function writeStarts(path: string, addresses: number[]): void {
const buffer = new ArrayBuffer((STARTS_HEADER_WORDS + addresses.length) * 8);
const words = new BigUint64Array(buffer);
words[0] = STARTS_MAGIC;
words[1] = 1n;
words[2] = BigInt(addresses.length);
for (let i = 0; i < addresses.length; i++) words[STARTS_HEADER_WORDS + i] = BigInt(addresses[i]!);
writeFileSync(path, new Uint8Array(buffer));
}
/** Read a trace functrace.c wrote: first-entry addresses, slide already removed. */
function readTrace(path: string, name: string): number[] {
const raw = readFileSync(path);
if (raw.byteLength < TRACE_HEADER_WORDS * 8) throw new Error(`workload "${name}" wrote a truncated trace`);View on GitHub (pinned to 8c5296ac45)
Solutions
- Build the unstripped profiling binary first: `bun run build:release` produces `bun-profile`
- Pass exeName explicitly if your build names the unstripped binary differently (e.g. assertions builds)
- Sanity-check with `nm build/bun-profile | grep -c ' [tT] '` — it must be non-zero before rerunning
- If using a custom NM, verify its output still looks like `0000000000001234 t _functionName`
Example fix
// before — pointing at the stripped artifact
generateOrderFile({ buildDir, exeName: "bun" });
// after — the unstripped symbol-bearing binary
generateOrderFile({ buildDir, exeName: "bun-profile" }); Defensive patterns
Strategy: validation
Validate before calling
import { spawnSync } from "node:child_process";
const r = spawnSync(process.env.NM || "nm", [bunProfile], { maxBuffer: 1 << 29 });
const textSymbols = r.stdout
.toString()
.split("\n")
.filter((line) => /^[0-9a-f]+ [tT] \S+$/.test(line)).length;
if (textSymbols === 0) {
throw new Error(`${bunProfile} has no text symbols (stripped?) — rebuild unstripped with bun run build:release`);
} Prevention
- Never strip the profiling binary; keep build:release output unstripped for orderfile work
- If your build renames the artifact, always pass exeName pointing at the unstripped one
When it happens
Trigger: Pointing exeName (or the default name) at the stripped release `bun` instead of the unstripped `bun-profile`; a release configuration that strips during copy; an nm variant that emits a different line format so every line fails the regex.
Common situations: Running generate against the wrong artifact in build output; build scripts changed to strip; switching nm implementations (some print symbol type in a different column).
Related errors
- ${nm} failed on ${bunProfile} ${r.stderr}
- workload "${name}" wrote a truncated trace
- the order file tracer builds on linux x86-64/arm64 or macOS
- ${bunProfile} not found — build it first (bun run build:rele
- could not pack the install fixture ${pack.stderr}
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/a72ebbde60e7971e.
Report an issue: GitHub.