nodejs/node
Debugging
This page collects the moves you actually use when something is wrong: getting a debug build, attaching a debugger, chasing memory issues, and reading Node's own diagnostic surfaces.
Getting a debug build
./configure --debug
make -j"$(nproc)"That produces out/Debug/node with full assertions, debug symbols, and the DCHECKs in src/util.h enabled. Most C++ debugging starts here. For diff-against-release behaviour you can also build both:
./configure --debug && make -j
mv out/Debug out/Debug.preserved
./configure && make -j
mv out/Debug.preserved out/DebugA separate set of flags exists for sanitizers:
| Flag | Effect |
|---|---|
--enable-asan |
AddressSanitizer build (catches use-after-free, OOB) |
--enable-ubsan |
UndefinedBehaviorSanitizer |
--enable-tsan |
ThreadSanitizer (rarely used; partial) |
Suppression files ship at tools/lsan_suppressions.txt and tools/valgrind.supp. The make test-asan target runs the suite under ASan.
Native debugger workflow
Linux:
gdb --args ./out/Debug/node --no-deprecation --inspect-brk=0 app.js
(gdb) catch throw
(gdb) catch syscall
(gdb) btmacOS:
lldb -- ./out/Debug/node app.js
(lldb) breakpoint set -n node::Start
(lldb) runUseful breakpoints:
node::errors::TriggerUncaughtException(src/node_errors.cc) — JS uncaught exceptions reach C++ here.node::Environment::AbortOnUncaughtException—--abort-on-uncaught-exception.node::TLSWrap::EncOut(src/crypto/crypto_tls.cc) — common TLS flow point.uv__io_poll(indeps/uv/src/unix/) — bottom of the event loop.node::Realm::ExecuteBootstrapper(src/node_realm.cc) — early bootstrap.
Use print *env after grabbing an Environment* — Environment has a debug printer in src/env.cc.
Attaching to V8 via the inspector
node --inspect=0.0.0.0:9229 app.js
node --inspect-brk app.js- Open
chrome://inspect(or use VS Code's "Attach to Node Process") to connect. - The inspector C++ implementation lives at
src/inspector/,src/inspector_*.{cc,h}, with the JS bindings atlib/inspector.jsandlib/internal/inspector/. --inspect-publish-uid=http,stderrcontrols how the WebSocket URL is published.- The
--inspect-wait(≥ Node 22) flag pauses until a debugger attaches even mid-script.
Programmatic access is via the inspector module: inspector.open(port, host, wait) and inspector.url(). Sessions can be opened in-process via new inspector.Session().
Reading runtime diagnostics
--report-on-fatalerror,--report-uncaught-exception,--report-on-signal— emit a JSONprocess.reportdump. Implementation:src/node_report.cc.--prof— writes V8isolate-*.logticks; post-process withnode --prof-process(which useslib/internal/main/prof_process.js).--trace-events-enabled --trace-event-categories=...— perfetto-format trace files. Implementation:src/tracing/.NODE_DEBUG=<area>— enablesutil.debuglog(area)calls scattered throughlib/internal/. Common values:module,tls,stream,tracing.NODE_DEBUG_NATIVE=<area>— toggles the C++ counterpart insrc/debug_utils.cc. Active areas are listed insrc/debug_utils.h.
process.report (always available) returns a JSON dump including loaded native code locations, async-resource trees, and libuv handles.
Async-context debugging
--async-stack-traces— V8 async stack traces (on by default).process.getActiveResourcesInfo()— lists everything keeping the loop alive.async_hooks.executionAsyncResource()— current async resource.AsyncLocalStorageis implemented inlib/internal/async_local_storage/overAsyncContextFrame(src/async_context_frame.cc).
Memory and leaks
--inspect+ Chrome DevTools heap snapshots is the easiest first step.--heapsnapshot-near-heap-limit=<n>triggers automatic snapshots before OOM.--heapsnapshot-signal=SIGUSR2writes a snapshot on demand.- For C++ leaks, the ASan build (
--enable-asan) is canonical. - For libuv handle leaks,
process._getActiveHandles()andprocess._getActiveRequests()are direct windows into uv handle/req trees.
Crash dumps
--report-on-fatalerrorwrites a JSON report immediately before abort.- On Linux, ensure
kernel.core_patternis set to capture cores; thengdb -c core ./out/Debug/node. - For postmortem analysis with
mdb/llnode, seedoc/contributing/postmortem.md.
Reproducing flaky tests
# Loop a single test 50 times under stress
python3 tools/test.py --repeat=50 -J test/parallel/test-foo.js
# Use `flaky-tests-mode` to allow CI to retry transient failures
python3 tools/test.py --flaky-tests=run test/parallel/...Flaky tests are tracked via the flaky-test GitHub label and .github/workflows/label-flaky-test-issue.yml.
When all else fails
- Diff against
out/Release/nodefrom a known-good build. - Bisect with
git bisect run python3 tools/test.py test/parallel/test-foo.js. - Ask in
#nodejs-coreon the OpenJS Foundation Slack with a stable repro.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.