TypeScript Debugging
When to Use This Skill
| Scenario |
Use this skill |
Alternative |
| Setting up Bun inspector for debugging |
Yes |
N/A |
| Configuring VSCode launch.json for Bun |
Yes |
N/A |
| Investigating memory leaks with heap snapshots |
Yes |
N/A |
| CPU profiling TypeScript applications |
Yes |
N/A |
| Debugging network requests with verbose fetch |
Yes |
N/A |
| Setting up sourcemaps for debugging |
Yes |
bun-development for build-time sourcemap flags |
| Monitoring errors in production |
No - use typescript-sentry |
N/A |
| Running tests to find failures |
No - use bun-development |
bun-test for quick test runs |
Core Expertise
Modern debugging for TypeScript/JavaScript with Bun runtime:
- WebKit Inspector Protocol (debug.bun.sh)
- VSCode integration with Bun extension
- Memory profiling with V8 heap snapshots
- Automatic sourcemap generation for TypeScript
- Chrome DevTools for heap analysis
Inspector Flags
Basic Debugging
# Start with debugger enabled
bun --inspect script.ts
# Custom port
bun --inspect=4000 script.ts
# Custom host:port
bun --inspect=localhost:4000 script.ts
Break on Start
# Break at first line (for fast scripts)
bun --inspect-brk script.ts
# Wait for debugger before running
bun --inspect-wait script.ts
Debugging Tests
# Debug test file
bun --inspect test
# Break before tests run
bun --inspect-brk test auth.test.ts
Web Debugger (debug.bun.sh)
Bun's built-in web debugger is a modified WebKit Web Inspector:
# Start debugging - outputs debug URL
bun --inspect script.ts
# ------------------- Bun Inspector -------------------
# Listening: ws://localhost:6499/
# Open: debug.bun.sh/#localhost:6499
# -----------------------------------------------------
Features
| Feature |
Description |
| Source view |
View original TypeScript/JSX with sourcemaps |
| Breakpoints |
Click line numbers to set/remove |
| Console |
Execute code in current context |
| Call stack |
Inspect execution frames |
| Scope |
View local/closure/global variables |
| Watch |
Add expressions to monitor |
Execution Controls
| Control |
Action |
| Continue (F8) |
Run until next breakpoint |
| Step Over (F10) |
Execute line, skip into functions |
| Step Into (F11) |
Enter function call |
| Step Out (Shift+F11) |
Complete function, return to caller |
VSCode Integration
Extension Setup
Install Bun for Visual Studio Code.
launch.json Configuration
{
"version": "0.2.0",
"configurations": [
{
"type": "bun",
"request": "launch",
"name": "Debug Script",
"program": "${workspaceFolder}/src/index.ts",
"cwd": "${workspaceFolder}",
"stopOnEntry": false,
"watchMode": false
},
{
"type": "bun",
"request": "launch",
"name": "Debug Tests",
"program": "${workspaceFolder}/tests/index.test.ts",
"cwd": "${workspaceFolder}",
"runtime": "bun",
"runtimeArgs": ["test"]
},
{
"type": "bun",
"request": "launch",
"name": "Debug with Watch",
"program": "${workspaceFolder}/src/index.ts",
"watchMode": true
},
{
"type": "bun",
"request": "attach",
"name": "Attach to Bun",
"url": "ws://localhost:6499/"
}
]
}
Configuration Options
| Option |
Type |
Description |
program |
string |
Entry file path |
cwd |
string |
Working directory |
args |
string[] |
Arguments to script |
env |
object |
Environment variables |
stopOnEntry |
boolean |
Break at first line |
watchMode |
boolean |
Enable --watch/--hot |
noDebug |
boolean |
Run without debugger |
strictEnv |
boolean |
Only use specified env |
Memory Debugging
Heap Snapshots
Create snapshots for Chrome DevTools analysis:
import { writeHeapSnapshot } from "v8";
// Create snapshot at any point
writeHeapSnapshot("before.heapsnapshot");
// After suspect operation
doSomeWork();
writeHeapSnapshot("after.heapsnapshot");
Load .heapsnapshot files in Chrome DevTools Memory tab for comparison.
Heap Statistics (bun:jsc)
import { heapStats } from "bun:jsc";
const stats = heapStats();
console.log({
heapSize: stats.heapSize,
objectCount: stats.objectCount,
objectTypeCounts: stats.objectTypeCounts
});
// objectTypeCounts: { Array: 1234, Object: 5678, Function: 890, ... }
Process Memory
// Resident Set Size (actual RAM used)
console.log(process.memoryUsage.rss());
// Full memory breakdown
console.log(process.memoryUsage());
// { rss, heapTotal, heapUsed, external, arrayBuffers }
Non-JS Memory (mimalloc)
# Show native memory stats
MIMALLOC_SHOW_STATS=1 bun script.ts
Performance Profiling
CPU Profiling
# Generate CPU profile
bun --cpu-prof script.ts
# Produces .cpuprofile file for Chrome DevTools
Network Request Debugging
# Log all fetch/http requests
BUN_CONFIG_VERBOSE_FETCH=1 bun script.ts
# Log as curl commands
BUN_CONFIG_VERBOSE_FETCH=curl bun script.ts
Sourcemaps
Bun automatically generates sourcemaps for transpiled files:
- TypeScript → JavaScript mapping preserved
- JSX transformations tracked
- Stack traces show original source locations
- Debugger shows TypeScript, not transpiled JS
Build with Sourcemaps
# External sourcemaps (recommended for debugging)
bun build ./src/index.ts --outdir=dist --sourcemap=external
# Inline sourcemaps
bun build ./src/index.ts --outdir=dist --sourcemap=inline
# No sourcemaps (production)
bun build ./src/index.ts --outdir=dist --sourcemap=none
Console Debugging
Beyond console.log
// Structured object/array display
console.table([{ id: 1, name: "a" }, { id: 2, name: "b" }]);
// Timing operations
console.time("fetch");
await fetch(url);
console.timeEnd("fetch"); // fetch: 234ms
// Group related logs
console.group("Request");
console.log("URL:", url);
console.log("Method:", method);
console.groupEnd();
// Conditional logging
console.assert(value > 0, "Value must be positive", value);
// Stack trace without error
console.trace("Reached here");
Programmatic Breakpoints
// Pause execution when debugger attached
debugger;
// Conditional breakpoint
if (suspiciousCondition) {
debugger;
}
Common Leak Patterns
Closure Entrapment
// BAD: largeData retained in closure
const largeData = loadHugeArray();
setInterval(() => {
console.log(largeData.length); // Keeps largeData alive forever
}, 1000);
// GOOD: Copy only needed data
const dataLength = largeData.length;
setInterval(() => {
console.log(dataLength);
}, 1000);
Event Listener Cleanup
// BAD: Listener never removed
emitter.on("data", handler);
// GOOD: Use once for single events
emitter.once("data", handler);
// GOOD: Explicit cleanup
emitter.on("data", handler);
// Later...
emitter.removeListener("data", handler);
AbortSignal/AbortController
// For long-running operations
const controller = new AbortController();
const response = await fetch(url, { signal: controller.signal });
// Cleanup on timeout
setTimeout(() => controller.abort(), 30000);
Module-Level Variables
// BAD: Grows indefinitely
const cache: Map<string, Data> = new Map();
export function getData(key: string) {
if (!cache.has(key)) {
cache.set(key, expensiveCompute(key));
}
return cache.get(key);
}
// GOOD: Use LRU or TTL cache
import { LRUCache } from "lru-cache";
const cache = new LRUCache<string, Data>({ max: 1000 });
Debugging Workflow
Memory Leak Investigation
- Baseline: Create heap snapshot at startup
- Reproduce: Perform suspect operations
- Compare: Create second snapshot, compare in DevTools
- Identify: Look for growing object counts (Delta column)
- Trace: Use retainers view to find what's holding references
Performance Investigation
- Profile: Run with
--cpu-prof
- Load: Open
.cpuprofile in Chrome DevTools
- Analyze: Check flame graph for hot paths
- Optimize: Focus on widest flames first
Agentic Optimizations
| Context |
Command |
| Quick debug |
bun --inspect-brk script.ts |
| Debug tests |
bun --inspect-brk test |
| Memory check |
bun -e "import{heapStats}from'bun:jsc';console.log(heapStats())" |
| Network debug |
BUN_CONFIG_VERBOSE_FETCH=curl bun script.ts |
| CPU profile |
bun --cpu-prof script.ts |
| Native memory |
MIMALLOC_SHOW_STATS=1 bun script.ts |
Quick Reference
Inspector Flags
| Flag |
Description |
--inspect |
Enable debugger on available port |
--inspect=<port> |
Enable debugger on specific port |
--inspect-brk |
Break at first line |
--inspect-wait |
Wait for debugger attachment |
--cpu-prof |
Generate CPU profile |
Debug URLs
| URL |
Purpose |
debug.bun.sh |
Bun's web debugger |
chrome://inspect |
Chrome DevTools (for heap analysis) |
Environment Variables
| Variable |
Description |
BUN_CONFIG_VERBOSE_FETCH |
1 or curl for request logging |
MIMALLOC_SHOW_STATS |
1 to show native memory stats |
Memory APIs
| API |
Import |
Purpose |
writeHeapSnapshot() |
v8 |
Create heap snapshot file |
heapStats() |
bun:jsc |
Get heap statistics |
memoryUsage() |
process |
Get process memory |
memoryUsage.rss() |
process |
Get resident set size |
Troubleshooting
Debugger Not Connecting
# Check if port is in use
lsof -i :6499
# Try explicit port
bun --inspect=9229 script.ts
Breakpoints Not Hit
- Ensure sourcemaps are enabled
- Use
--inspect-brk for fast-exiting scripts
- Check file paths match in debugger
VSCode Issues (Windows)
Bun's Unix socket debugging may not work on Windows. Use WSL or the web debugger instead.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.