Skip to main content
This guide covers various techniques for debugging Deno’s Rust code, JavaScript runtime, and tests.

Debugging Rust Code

Using an IDE Debugger

The recommended approach for debugging Rust code is using your IDE’s built-in debugger.
Setup:
  1. Install the rust-analyzer extension
  2. Install the CodeLLDB extension
Create .vscode/launch.json:
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug Deno",
      "cargo": {
        "args": [
          "build",
          "--bin=deno",
          "--package=deno"
        ],
        "filter": {
          "name": "deno",
          "kind": "bin"
        }
      },
      "args": ["run", "--allow-all", "test.ts"],
      "cwd": "${workspaceFolder}"
    }
  ]
}
Usage:
  1. Set breakpoints in Rust code by clicking in the gutter
  2. Press F5 to start debugging
  3. Use standard debugging controls (step, continue, etc.)

Debug Print Statements

Quick debugging with print statements:
// Standard error output (doesn't interfere with stdout)
eprintln!("Debug: {:?}", variable);

// Debug macro (prints file, line, and value)
dbg!(variable);
dbg!(&some_struct);

// Conditional debugging
#[cfg(debug_assertions)]
eprintln!("Debug mode: {:?}", data);
Use eprintln! instead of println! to avoid interfering with program output.

Verbose Logging

Enable detailed logging output:
# Set log level to debug
DENO_LOG=debug ./target/debug/deno run script.ts

# Log specific modules
DENO_LOG=deno_core=debug ./target/debug/deno run script.ts
DENO_LOG=deno_fetch=trace ./target/debug/deno run script.ts

# Multiple modules
DENO_LOG=deno_core=debug,deno_fetch=trace ./target/debug/deno run script.ts
Log Levels:
  • error - Errors only
  • warn - Warnings and errors
  • info - Informational messages
  • debug - Debug information
  • trace - Very verbose output

Using the log Crate

Add logging to your code:
use log::{debug, info, warn, error};

fn my_function() {
  debug!("Starting operation");
  info!("Processing file: {}", path);
  warn!("Deprecated API used");
  error!("Operation failed: {}", err);
}

Debugging JavaScript Runtime

Chrome DevTools Inspector

Deno supports the Chrome DevTools Protocol for debugging JavaScript:
1

Start with inspector

# Break on first line
./target/debug/deno run --inspect-brk script.ts

# Break on exception
./target/debug/deno run --inspect script.ts

# Custom port
./target/debug/deno run --inspect=127.0.0.1:9229 script.ts
2

Connect DevTools

  1. Open Chrome browser
  2. Navigate to chrome://inspect
  3. Click “inspect” under your Deno process
  4. DevTools will open
3

Debug

  • Set breakpoints in the Sources tab
  • Step through code
  • Inspect variables in the Scope panel
  • Use the Console for REPL
The --inspect-brk flag breaks on the first line of code, while --inspect allows the program to run until you set a breakpoint.

Console Debugging

JavaScript console methods:
// Basic logging
console.log("Message", variable);
console.debug("Debug info");
console.info("Info");
console.warn("Warning");
console.error("Error");

// Formatted output
console.log("User: %s, Age: %d", name, age);

// Object inspection
console.dir(object);
console.table(array);

// Timing
console.time("operation");
// ... code ...
console.timeEnd("operation");

// Stack trace
console.trace("Trace point");

Debugging Tests

Running Tests in Debug Mode

# Run test with output
cargo test test_name -- --nocapture

# Run test with debug logging
DENO_LOG=debug cargo test test_name -- --nocapture

# Run single test
cargo test test_name --exact -- --nocapture

Debugging Spec Tests

# Run specific spec test with output
cargo test spec::run::basic -- --nocapture

# Debug spec test failures
DENO_LOG=debug cargo test spec::my_test -- --nocapture

Debugging Test in IDE

VS Code:
  1. Click the “Debug” link above #[test] function (requires rust-analyzer)
  2. Or add to .vscode/launch.json:
{
  "type": "lldb",
  "request": "launch",
  "name": "Debug Test",
  "cargo": {
    "args": [
      "test",
      "--no-run",
      "--lib",
      "--package=deno"
    ]
  },
  "args": ["test_name", "--exact"],
  "cwd": "${workspaceFolder}"
}

Performance Debugging

Backtraces

Get detailed stack traces:
# Basic backtrace
RUST_BACKTRACE=1 ./target/debug/deno run script.ts

# Full backtrace with source locations
RUST_BACKTRACE=full ./target/debug/deno run script.ts

Profiling

# Build release binary
cargo build --release

# Record profile
perf record -g ./target/release/deno run script.ts

# View report
perf report

# Generate flamegraph
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg

Memory Debugging

# Use Valgrind (Linux)
valgrind --leak-check=full ./target/debug/deno run script.ts

# Use heaptrack (Linux)
heaptrack ./target/debug/deno run script.ts
heaptrack_gui heaptrack.deno.12345.gz

Common Debugging Scenarios

Steps:
  1. Enable backtrace:
    RUST_BACKTRACE=full ./target/debug/deno run script.ts
    
  2. Look for the panic message and location
  3. Set a breakpoint before the panic in debugger
  4. Examine variable state at crash point
Steps:
  1. Profile the code:
    cargo build --release
    perf record -g ./target/release/deno run script.ts
    perf report
    
  2. Look for hot functions in the profile
  3. Add timing logs:
    let start = Instant::now();
    // ... operation ...
    eprintln!("Operation took: {:?}", start.elapsed());
    
  4. Optimize hot paths
Steps:
  1. Enable debug logging:
    DENO_LOG=deno_core=debug ./target/debug/deno run script.ts
    
  2. Look for “Resolving” and “Loading” messages
  3. Check module_loader.rs with breakpoints
  4. Verify import map and resolution logic
Steps:
  1. Check permission flags:
    ./target/debug/deno run --allow-read --allow-write script.ts
    
  2. Add debug logging in permission checks:
    eprintln!("Checking read permission for: {}", path);
    
  3. Set breakpoint in runtime/permissions/
  4. Verify permission state
Steps:
  1. Add logging to the op:
    #[op2]
    fn op_my_op(arg: String) -> Result<String, AnyError> {
      eprintln!("op_my_op called with: {}", arg);
      // ...
    }
    
  2. Check JavaScript console for errors
  3. Use inspector to see JS stack trace
  4. Set breakpoint in op implementation

Advanced Debugging

Debugging V8

Debug V8-specific issues:
# Enable V8 debug output
DENO_V8_FLAGS="--trace-opt --trace-deopt" ./target/debug/deno run script.ts

# Trace inline caching
DENO_V8_FLAGS="--trace-ic" ./target/debug/deno run script.ts

# Trace garbage collection
DENO_V8_FLAGS="--trace-gc" ./target/debug/deno run script.ts

Core Dumps

Generate and analyze core dumps:
# Enable core dumps (Linux)
ulimit -c unlimited

# Run program (will generate core file on crash)
./target/debug/deno run script.ts

# Debug with core dump
lldb ./target/debug/deno -c core
(lldb) bt  # Show backtrace

Remote Debugging

Debug on remote machines:
# Start with inspector on all interfaces
./target/debug/deno run --inspect=0.0.0.0:9229 script.ts

# Connect from local machine to remote:9229 via SSH tunnel
ssh -L 9229:localhost:9229 user@remote

# Open chrome://inspect and connect to localhost:9229

Debugging Tools Summary

IDE Debugger

Best for step-by-step debuggingUse when: Tracing logic flow, inspecting variables

Print Debugging

Quick and simpleUse when: Quick checks, production debugging

Chrome DevTools

JavaScript debuggingUse when: Debugging JS runtime issues

Logging

Runtime diagnosticsUse when: Tracking execution flow, production issues

Profiler

Performance analysisUse when: Finding bottlenecks, optimizing

Backtrace

Crash analysisUse when: Diagnosing panics, segfaults

Troubleshooting Tips

1

Reproduce the issue

Create a minimal test case that reproduces the problem consistently.
2

Gather information

  • What’s the error message?
  • What’s the stack trace?
  • What are the inputs?
  • What’s the expected vs actual behavior?
3

Narrow down the cause

  • Use print debugging to find where it fails
  • Use bisection: comment out code to isolate the issue
  • Check recent changes with git log
4

Use appropriate tools

  • Debugger for complex logic
  • Profiler for performance
  • Inspector for JavaScript
  • Logging for understanding flow
5

Fix and verify

  • Make the fix
  • Add a test to prevent regression
  • Verify the fix works

Getting Help

If you’re stuck:
  1. Search existing issues on GitHub
  2. Ask in Discord - Deno Discord
  3. Open a discussion on GitHub Discussions
  4. File an issue with reproduction steps
When asking for help, always provide:
  • Deno version (deno --version)
  • Operating system
  • Minimal reproduction code
  • Error messages and stack traces

Next Steps

Testing

Learn about testing Deno

Code Structure

Understand the codebase structure

Build docs developers (and LLMs) love