Skip to main content
Bun includes built-in debugger support compatible with Chrome DevTools, VS Code, and other debugging clients using the WebSocket Inspector protocol.

Quick Start

Start Bun with debugging enabled:
Debug mode
bun --inspect run app.ts
Connect with Chrome DevTools:
  1. Open chrome://inspect in Chrome
  2. Click “Configure” and add localhost:6499
  3. Click “inspect” on your Bun process

Inspector Options

—inspect

Start inspector on default port (6499):
Default inspector
bun --inspect run server.ts
Behavior:
  • Starts WebSocket inspector server
  • Continues execution immediately
  • Debugger can attach at any time

—inspect-wait

Wait for debugger before executing:
Wait for debugger
bun --inspect-wait run app.ts
Behavior:
  • Starts inspector
  • Pauses execution until debugger attaches
  • Useful for debugging initialization code

—inspect-brk

Break on first line:
Break on start
bun --inspect-brk run app.ts
Behavior:
  • Starts inspector
  • Pauses on first line of code
  • Allows setting breakpoints before execution

Custom Port

Specify inspector port:
Custom port
bun --inspect=9229 run app.ts
bun --inspect=0.0.0.0:9229 run app.ts # Listen on all interfaces

Chrome DevTools

Use Chrome’s built-in debugger:

Setup

  1. Start Bun with --inspect:
    bun --inspect run app.ts
    
  2. Open Chrome and navigate to:
    chrome://inspect
    
  3. Under “Remote Target”, click Configure
  4. Add inspector URL:
    localhost:6499
    
  5. Click Inspect on your Bun process

Features

  • View source files with TypeScript support
  • Set breakpoints by clicking line numbers
  • Step through code (F10, F11)
  • Watch expressions
  • Call stack navigation
  • Evaluate expressions in paused context
  • View console.log output
  • Inspect objects interactively
  • Execute code at breakpoints
  • CPU profiling
  • Memory heap snapshots
  • Performance timeline
  • HTTP request/response inspection
  • WebSocket frame monitoring
  • Timing analysis

VS Code Debugging

Integrate with Visual Studio Code:

Launch Configuration

Create .vscode/launch.json:
.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Bun",
      "runtimeExecutable": "bun",
      "runtimeArgs": ["run", "--inspect-wait"],
      "program": "${workspaceFolder}/src/index.ts",
      "console": "integratedTerminal",
      "skipFiles": ["<node_internals>/**"],
      "smartStep": true,
      "sourceMaps": true
    }
  ]
}

Attach Configuration

Attach to running Bun process:
Attach configuration
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "Attach to Bun",
      "port": 6499,
      "skipFiles": ["<node_internals>/**"],
      "sourceMaps": true,
      "resolveSourceMapLocations": [
        "${workspaceFolder}/**",
        "!**/node_modules/**"
      ]
    }
  ]
}

Debug Current File

Debug current file
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Current File",
      "runtimeExecutable": "bun",
      "runtimeArgs": ["run", "--inspect-wait"],
      "program": "${file}",
      "console": "integratedTerminal"
    }
  ]
}

Debugging Tests

Debug tests
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Tests",
      "runtimeExecutable": "bun",
      "runtimeArgs": ["test", "--inspect-wait"],
      "console": "integratedTerminal",
      "skipFiles": ["<node_internals>/**"]
    }
  ]
}

Usage

  1. Set breakpoints: Click in the gutter next to line numbers
  2. Start debugging: Press F5 or click “Run and Debug”
  3. Step through: Use F10 (step over), F11 (step into), Shift+F11 (step out)
  4. Inspect variables: Hover over variables or use the Variables panel
  5. Evaluate expressions: Use the Debug Console

Breakpoints

Line Breakpoints

Line breakpoints
function calculate(a: number, b: number) {
  const sum = a + b; // Click gutter to set breakpoint
  console.log(`Sum: ${sum}`);
  return sum;
}

Conditional Breakpoints

Conditional breakpoint
for (let i = 0; i < 100; i++) {
  // Right-click gutter > Add Conditional Breakpoint
  // Condition: i === 50
  console.log(i);
}

Logpoints

Log without stopping:
Logpoint
function process(data: any) {
  // Right-click gutter > Add Logpoint
  // Message: Processing {data.id}
  return transform(data);
}

Programmatic Breakpoints

Debugger statement
function debug() {
  // Pause execution when debugger attached
  debugger;
  console.log("After breakpoint");
}

Debugging Features

Call Stack

Navigate function call hierarchy:
Call stack
function outer() {
  inner();
}

function inner() {
  debugger; // Pause here - see outer() in call stack
  console.log("Inner");
}

outer();

Variable Inspection

Inspect variables
function example() {
  const user = { id: 1, name: "Alice" };
  const items = [1, 2, 3, 4, 5];
  
  debugger; // Hover over variables to inspect
  
  console.log(user, items);
}

Watch Expressions

Monitor expressions across breakpoints:
Watch expressions
let count = 0;

function increment() {
  count++; // Add watch: count, count * 2
  debugger;
}

for (let i = 0; i < 5; i++) {
  increment();
}

Console Evaluation

Evaluate code while paused:
Console evaluation
function test() {
  const x = 10;
  const y = 20;
  
  debugger;
  // In console: x + y, Math.max(x, y)
  
  return x + y;
}

Source Maps

Bun automatically generates source maps for TypeScript:
Original TypeScript
interface User {
  id: number;
  name: string;
}

function greet(user: User): string {
  return `Hello, ${user.name}!`;
}

greet({ id: 1, name: "Alice" });
Debugger shows original TypeScript, not transpiled JavaScript.

Inline Source Maps

Bun embeds source maps by default:
Generated output
// JavaScript output with inline source map
function greet(user) {
  return `Hello, ${user.name}!`;
}
//# sourceMappingURL=data:application/json;base64,...

External Source Maps

Generate separate .map files:
External source maps
bun build app.ts --sourcemap=external

Async Debugging

Debug async code:
Async debugging
async function fetchUser(id: number) {
  debugger; // Breakpoint before await
  
  const response = await fetch(`/api/users/${id}`);
  
  debugger; // Breakpoint after await
  
  const user = await response.json();
  return user;
}

fetchUser(1);
Features:
  • Step through promises
  • Inspect promise state
  • View async call stack

Exception Breaking

Pause on thrown exceptions:

DevTools

  1. Open Sources panel
  2. Click “Pause on exceptions” button (⏸)
  3. Choose:
    • Pause on caught exceptions
    • Pause on uncaught exceptions

VS Code

Breakpoints on exceptions
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug",
      "runtimeExecutable": "bun",
      "runtimeArgs": ["run", "--inspect-wait"],
      "program": "${workspaceFolder}/src/index.ts",
      "stopOnEntry": false,
      "console": "integratedTerminal",
      // Break on all exceptions
      "breakOnException": true
    }
  ]
}

Performance Profiling

CPU Profile

Profile CPU usage:
  1. Start Bun with --inspect
  2. Open Chrome DevTools
  3. Go to Profiler tab
  4. Click Record
  5. Run your code
  6. Click Stop
  7. Analyze flame graph

Memory Profiling

Analyze memory usage:
  1. Open Chrome DevTools
  2. Go to Memory tab
  3. Select Heap snapshot
  4. Click Take snapshot
  5. Inspect objects and allocations

Remote Debugging

Debug Bun running on remote server:

SSH Tunnel

SSH tunnel
# On remote server
bun --inspect=0.0.0.0:6499 run app.ts

# On local machine
ssh -L 6499:localhost:6499 user@remote-server
Connect to localhost:6499 from Chrome DevTools or VS Code.

Network Access

Allow network access
bun --inspect=0.0.0.0:6499 run app.ts
Only expose inspector on trusted networks! No authentication by default.

Implementation

Debugger implementation:
  • Inspector: src/js/internal/debugger.ts - WebSocket inspector server
  • Protocol: Chrome DevTools Protocol (CDP)
  • Source maps: src/sourcemap/ - Source map generation
  • Runtime: src/runtime.zig:176 - Set breakpoint on first line flag
Debugger flag (src/runtime.zig:176)
set_breakpoint_on_first_line: bool = false,

Advanced Debugging

Multi-Process Debugging

Debug multiple Bun processes:
Multiple processes
# Terminal 1
bun --inspect=6499 run server.ts

# Terminal 2  
bun --inspect=6500 run worker.ts
Attach separate debuggers to each process.

Debugging Workers

Worker debugging
const worker = new Worker("worker.ts");

// worker.ts
console.log("Worker started");
debugger; // Pause in worker context
Start with --inspect to debug workers.

Debugging Tests

Debug tests
bun --inspect-brk test math.test.ts
Sets breakpoint before test execution.

Common Workflows

Debug HTTP Server

Debug server
import { serve } from "bun";

serve({
  port: 3000,
  fetch(req) {
    debugger; // Pause on each request
    return new Response("Hello!");
  },
});

Debug CLI Tool

Debug CLI
bun --inspect-wait run cli.ts --arg1 --arg2

Debug Build Script

Debug build
bun --inspect-wait run build.ts

Troubleshooting

Debugger Won’t Connect

  1. Check port: Ensure port 6499 is not in use
  2. Check firewall: Allow connections to inspector port
  3. Check URL: Verify ws://localhost:6499 in DevTools
Check port
lsof -i :6499  # macOS/Linux
netstat -ano | findstr :6499  # Windows

Breakpoints Not Hitting

  1. Check source maps: Ensure TypeScript files map correctly
  2. Verify file path: Use absolute paths in launch.json
  3. Clear cache: Remove .bun cache directory
Clear cache
rm -rf ~/.bun/install/cache

Source Maps Not Working

  1. Check inline maps: Bun generates inline maps by default
  2. Verify tsconfig: Check sourceMap option
  3. Check paths: Ensure file paths are absolute

VS Code Can’t Find Source

Source map locations
{
  "resolveSourceMapLocations": [
    "${workspaceFolder}/**",
    "!**/node_modules/**"
  ]
}

Debugging Tips

1. Use Conditional Breakpoints

Instead of:
for (let i = 0; i < 100; i++) {
  if (i === 50) {
    debugger; // Manual condition
  }
}
Use conditional breakpoint: i === 50

2. Logpoints Over console.log

Avoid modifying code:
  • Set logpoint instead of console.log
  • Message: User {user.id} - {user.name}

3. Watch Expressions

Monitor complex expressions:
  • user?.profile?.settings
  • items.filter(x => x.active).length

4. Copy Value

Right-click variable → Copy Value (in VS Code)

5. Restart Frame

Right-click call stack frame → Restart Frame (re-execute function)

Performance

Inspector overhead:
  • Minimal when not attached: <1% overhead
  • When attached: ~5-10% depending on breakpoints
  • Profiling active: ~20% overhead
Production recommendation: Disable inspector in production.

Security

Never expose inspector port publicly! No authentication mechanism.
Security best practices:
  1. Bind to localhost: --inspect=127.0.0.1:6499
  2. Use SSH tunnels: For remote debugging
  3. Firewall rules: Block inspector port from internet
  4. Disable in production: Remove --inspect flag

Build docs developers (and LLMs) love