{"record":{"id":"5d51093c6abf6cd6","repo":"oven-sh/bun","slug":"nm-failed-on-bunprofile-r-stderr","errorCode":null,"errorMessage":"${nm} failed on ${bunProfile}\n${r.stderr}","messagePattern":"(.+?) failed on (.+?)\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/orderfile/generate.ts","lineNumber":141,"sourceCode":"  /** Fail if fewer than this many functions were traced. */\n  minFunctions?: number;\n  /** Print per-workload progress. */\n  verbose?: boolean;\n}\n\n/**\n * Linker-visible function names, by address. Multiple names can share one\n * address (aliases, and ICF on darwin), and the order file must list every name\n * the linker might know a function by. On macOS nm prints names with the C\n * leading underscore, which is also what `-order_file` expects, so no\n * stripping — lld and ld take exactly what nm gave.\n */\nfunction readSymbolTable(bunProfile: string): Map<number, string[]> {\n  // Bare `nm` with no GNU-only long options: the regex below is the\n  // defined-text-symbol filter, and nothing here depends on output order.\n  const nm = process.env.NM || \"nm\";\n  const r = runCommand([nm, bunProfile]);\n  if (r.status !== 0) throw new Error(`${nm} failed on ${bunProfile}\\n${r.stderr}`);\n\n  const symbols = new Map<number, string[]>();\n  for (const line of r.stdout.toString().split(\"\\n\")) {\n    const m = /^([0-9a-f]+) ([tT]) (\\S+)$/.exec(line);\n    if (!m) continue;\n    const address = parseInt(m[1]!, 16);\n    const names = symbols.get(address);\n    if (names) names.push(m[3]!);\n    else symbols.set(address, [m[3]!]);\n  }\n  if (symbols.size === 0) throw new Error(`${nm} reported no text symbols — is ${bunProfile} stripped?`);\n  return symbols;\n}\n\n/** Write function starts for functrace.c: u64 magic, version, count, addresses. */\nfunction writeStarts(path: string, addresses: number[]): void {\n  const buffer = new ArrayBuffer((STARTS_HEADER_WORDS + addresses.length) * 8);\n  const words = new BigUint64Array(buffer);","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/scripts/orderfile/generate.ts#L123-L159","documentation":"While reading the unstripped bun-profile binary's symbol table, nm exited non-zero and its stderr is appended to the message. This is a tool/format-level failure — nm ran but refused or failed to parse the file — distinct from spawn errors (167) and from finding zero symbols (169).","triggerScenarios":"The NM env var (or bare `nm`) resolves to an nm that cannot parse the binary's object format (e.g. LLVM nm vs GNU nm disagreements, wrong-arch nm); the binary is truncated or corrupt from an interrupted build.","commonSituations":"Cross-compilation environments where the default nm targets another platform; Nix/conda shims shadowing binutils nm; partial build artifacts after a cancelled `bun run build:release`.","solutions":["Read the appended stderr — it names the parse problem","Check the file: `file <buildDir>/bun-profile` and confirm it matches the host format","Point NM at the platform-correct nm or unset the NM override so the default is used","Rebuild the binary (`bun run build:release`) if the file is corrupt or truncated"],"exampleFix":"# before\n$ NM=llvm-nm-15 bun scripts/orderfile/generate.ts\nError: llvm-nm-15 failed on build/bun-profile\n...\n\n# after — use the default platform nm\n$ env -u NM bun scripts/orderfile/generate.ts","handlingStrategy":"try-catch","validationCode":"import { spawnSync } from \"node:child_process\";\n\nconst probe = spawnSync(process.env.NM || \"nm\", [\"--version\"]);\nif (probe.error || probe.status !== 0) {\n  throw new Error(\"nm is missing or broken — fix NM/PATH before generating the order file\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return readSymbolTable(bunProfile);\n} catch (err) {\n  if (/failed on .*\\n/.test(String(err))) {\n    console.error(`nm could not parse ${bunProfile} — verify format/arch or set NM`);\n  }\n  throw err;\n}","preventionTips":["Use the nm that ships with the platform's default toolchain; avoid mixing LLVM and GNU nm across cross-builds","Regenerate the build rather than tracing half-written artifacts after cancelled builds"],"tags":["toolchain","binary","symbols","nm","orderfile"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}