Open-Source Wikis

/

Bun

/

How to contribute

/

Debugging

oven-sh/bun

Debugging

This page is the practical "what do I do when something is wrong" reference.

A test crashes

  1. Run with the debug build: bun bd test <file>.
  2. The crash handler prints a bun.report URL with both Zig and JS frames. Open it.
  3. If you have a debugger attached, the address sanitiser flag may help: bun bd --asan=on test <file> (slower, catches more).
  4. To get exception-scope diagnostics from JSC: BUN_JSC_validateExceptionChecks=1 BUN_JSC_dumpSimulatedThrows=1 bun bd ....

A test hangs

  1. Find which test hung: bun bd test <file> --timeout=10000 and look at the last "starting" log line.
  2. Common culprits: an unawaited promise, a missing port: 0, or a process started without a using declaration.
  3. BUN_DEBUG_QUIET_LOGS=1 BUN_DEBUG_EVENTLOOP=1 bun bd ... shows event-loop tick boundaries.

A change builds locally but fails in CI

  1. Run bun run ci:errors (or bun run ci:errors '#PR') for a rendered failure list.
  2. Run bun run ci:logs to save full job logs to ./tmp/ci-<build>/.
  3. Common platform differences:
    • Windows: long paths, file locking, \r\n line endings, Unicode codepage. Use bun.path.windows and bun.sys.openat rather than POSIX-only paths.
    • macOS: code signing for FFI, FSEvents debounce.
    • Linux: epoll vs kqueue, glibc vs musl on Alpine images.

Debug-log scopes

Set BUN_DEBUG_<name>=1 to enable a specific scope. Examples observed in source:

  • BUN_DEBUG_HTTP=1 — HTTP client request lifecycle.
  • BUN_DEBUG_FFI=1 — FFI marshalling.
  • BUN_DEBUG_INSTALL=1 — Package manager.
  • BUN_DEBUG_BUNDLER=1 — Bundler steps.
  • BUN_DEBUG_PARSER=1 — Parser entry / exit.
  • BUN_DEBUG_RESOLVER=1 — Module resolution attempts.
  • BUN_DEBUG_QUIET_LOGS=1 — Disable everything else (useful when chaining).

The full list lives in Output.scoped(.<name>, .visible) declarations across the source. Grep for Output.scoped( in src/.

Sourcemaps

Bun builds with sourcemap markers always available. The crash handler uses them to print human-readable file:line for native frames. For JS frames in user code, sourcemap support is automatic when the code was bundled by Bun.

The inspector

bun --inspect <script> opens an inspector socket; chrome://inspect will pick it up. The protocol is JSC's standard one. The bundled bun-vscode extension (packages/bun-vscode/) attaches via the same protocol.

Profiling

bun bd --cpu-prof script.ts

Produces a .cpuprofile file. Open in Chrome DevTools → Performance.

For a hot Zig path, build with Tracy support and use vendor/tracy/ (not on by default — see scripts/build/).

Memory leaks

Use Bun.gc(true) in tests to force a full GC, then check process.memoryUsage(). The gc helper is also exported from harness.ts.

For native leaks, mimalloc has built-in stats: MIMALLOC_VERBOSE=1 bun bd ....

A C++ assert fires

The error message includes file:line. Search the file. C++ asserts in JSC bindings (ASSERT(...) macros) usually mean a bug in the binding — wrong owner, wrong scope, missing exception check.

A Zig unreachable fires

This is a panic. The crash handler kicks in, gives you a bun.report URL with the offending function. Often the fix is to convert unreachable into an error or to explicitly handle the case.

A test passes locally but fails in CI

Order of likelihood:

  1. Flakiness. Look for setTimeout, port reuse, ordering dependencies.
  2. Platform. Re-read the failing job's OS. Add the platform-specific path with if (process.platform === "win32").
  3. Missing CI env var. Some integration tests require credentials only set in CI — those should be test.skipIf blocked locally.
  4. Resource limits. CI runners have less RAM; tests that pre-allocate large buffers may OOM.

Reading PR feedback

gh pr view --comments silently omits review comments. Always use:

bun run pr:comments
bun run pr:comments 28838
bun run pr:comments --include-resolved
bun run pr:comments --json | jq '.[] | select(.user == "...")'

This pulls all three GitHub comment endpoints and presents them in one chronological list.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Debugging – Bun wiki | Factory