{"record":{"id":"c7815f50f09b148e","repo":"oven-sh/bun","slug":"traced-only-order-length-functions-expected-at","errorCode":null,"errorMessage":"traced only ${order.length} functions, expected at least ${minFunctions} — the tracer or the symbol table is broken, and a near-empty order file silently costs the win","messagePattern":"traced only (.+?) functions, expected at least (.+?) — the tracer or the symbol table is broken, and a near-empty order file silently costs the win","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/orderfile/generate.ts","lineNumber":328,"sourceCode":"      let unresolved = 0;\n      for (const address of readTrace(out, workload.name)) {\n        const names = symbols.get(address);\n        if (!names) {\n          unresolved++;\n          continue;\n        }\n        for (const name of names) {\n          if (seen.has(name)) continue;\n          seen.add(name);\n          order.push(name);\n        }\n      }\n      const note = unresolved ? ` (${unresolved} unresolved)` : \"\";\n      log(`  ${workload.name.padEnd(21)} +${order.length - before} functions${note}`);\n    }\n\n    if (order.length < minFunctions) {\n      throw new Error(\n        `traced only ${order.length} functions, expected at least ${minFunctions} — ` +\n          `the tracer or the symbol table is broken, and a near-empty order file silently costs the win`,\n      );\n    }\n\n    const header = [\n      `# ${darwin ? \"ld -order_file\" : \"lld --symbol-ordering-file\"}: functions bun executes while starting up,`,\n      \"# in first-entry order, so they land together at the front of .text.\",\n      \"# Generated by scripts/orderfile/generate.ts — not committed.\",\n      `# ${order.length} functions from ${workloads.length} workloads.`,\n    ];\n    writeFileSync(outPath, header.join(\"\\n\") + \"\\n\" + order.join(\"\\n\") + \"\\n\");\n    return { count: order.length, outPath };\n  } finally {\n    rmSync(scratch, { recursive: true, force: true });\n  }\n}\n","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/scripts/orderfile/generate.ts#L310-L346","documentation":"Final sanity gate in generateOrderFile: after every workload, fewer than minFunctions (default MIN_FUNCTIONS) unique symbol names were collected. A near-empty order file would silently forfeit the link-order startup win, so the generator fails loudly instead of writing a useless artifact.","triggerScenarios":"Most traced addresses failing to resolve because the symbol table came from a different build than the binary executed; the tracer not loading in workloads (each trace would be empty or all-unresolved); a stripped or mismatched bun-profile. Watch the verbose per-workload `+N functions (X unresolved)` lines to see where resolution dies.","commonSituations":"Rebuilding the binary between generating the symbol table and running workloads; mixing binaries (default name vs custom exeName); tracer silently not preloading on hardened setups.","solutions":["Re-run with verbose enabled and read the per-workload counts — a large `(unresolved)` number means address/symbol mismatch","Ensure the bun-profile passed to nm is byte-identical to the binary the workloads executed (rebuild once, then generate in one step)","Confirm the tracer actually preloads in every workload (see error 172 diagnosis)","Only if you intentionally traced a much smaller binary, lower minFunctions accordingly"],"exampleFix":"// before — silently accepts a near-empty order file\ngenerateOrderFile({ buildDir });\n\n// after — gate explicitly on a realistic floor\ngenerateOrderFile({ buildDir, minFunctions: 10_000, verbose: true });","handlingStrategy":"try-catch","validationCode":"import { spawnSync } from \"node:child_process\";\n\n// Cheap coverage probe: how many text symbols can this nm even see for this binary?\nconst r = spawnSync(process.env.NM || \"nm\", [bunProfile]);\nconst visible = r.stdout.toString().split(\"\\n\").filter((l) => /^[0-9a-f]+ [tT] \\S+$/.test(l)).length;\nif (visible < minFunctions) throw new Error(`Symbol table only exposes ${visible} functions — minFunctions ${minFunctions} can never be met`);","typeGuard":null,"tryCatchPattern":"try {\n  return generateOrderFile({ buildDir, verbose: true });\n} catch (err) {\n  if (/traced only \\d+ functions/.test(String(err))) {\n    console.error(\"Order file would be near-empty — verify tracer preload and that nm read the exact binary that ran\");\n  }\n  throw err;\n}","preventionTips":["Always run generation with verbose:true when iterating; the per-workload `+N (X unresolved)` lines localize the breakage","Generate the order file in the same CI step that built bun-profile so symbol table and traced binary cannot diverge","Treat a sudden drop in traced-function counts as a real regression, never silence it by lowering minFunctions"],"tags":["orderfile","symbols","tracing","sanity-check"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}