← Debugging Guides

阅读中文版本

Node Inspector Port In Use — Debugger Cannot Attach

Resolve "address already in use" and debugger attach failures by finding the process holding port 9229 and selecting a different inspector port.

beginnerdebuggingnodejsdebuggernetworking

Symptoms

  • Node prints "Starting inspector on 127.0.0.1:9229 failed: address already in use"
  • The IDE debugger connects to the wrong process or not at all
  • A previous run that crashed still holds the debug port

Possible causes

  • A stale Node process from an earlier debug session still listens on 9229
  • Another tool or IDE already binds the same inspector port
  • node --inspect is started while a --inspect-brk session is already running

Diagnosis steps

Find the process holding the port

lsof -i :9229 || ss -ltnp | grep 9229

Interpretation

The PID and command tell you whether it is a stale Node run or an unrelated tool.

Start the inspector on a free port

node --inspect=127.0.0.1:9230 app.js

Interpretation

Any unused port works; update the IDE attach target to match.

Confirm the inspector endpoint responds

curl http://127.0.0.1:9230/json/list

Interpretation

A JSON list with a webSocketDebuggerUrl means the inspector is reachable and attach will succeed.

Root cause

Node inspector binds a TCP port (9229 by default). Only one process can bind a given address and port, so when a stale debug session still holds it the new inspector start fails and the debugger cannot attach.

Fix

Kill the stale process or choose a distinct port with --inspect-port/--inspect, and add a script that selects an available port to avoid collisions in scripts and CI.

Risk note

An inspector bound to 0.0.0.0 exposes a debugger to the network; always bind 127.0.0.1 outside local development.

Verify the fix

Start the app with the new port, open the inspector URL, and confirm the process appears in the target list; set a breakpoint to prove attach works.

Symptoms

This debugging guide addresses “Node Inspector Port In Use — Debugger Cannot Attach”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.

Observed symptoms include:

  • Node prints “Starting inspector on 127.0.0.1:9229 failed: address already in use”
  • The IDE debugger connects to the wrong process or not at all
  • A previous run that crashed still holds the debug port

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Find the process holding the port

lsof -i :9229 || ss -ltnp | grep 9229

The PID and command tell you whether it is a stale Node run or an unrelated tool.

Step 2: Start the inspector on a free port

node --inspect=127.0.0.1:9230 app.js

Any unused port works; update the IDE attach target to match.

Step 3: Confirm the inspector endpoint responds

curl http://127.0.0.1:9230/json/list

A JSON list with a webSocketDebuggerUrl means the inspector is reachable and attach will succeed.

Likely contributors, in order of frequency:

  • A stale Node process from an earlier debug session still listens on 9229
  • Another tool or IDE already binds the same inspector port
  • node –inspect is started while a –inspect-brk session is already running

Root Cause

Node inspector binds a TCP port (9229 by default). Only one process can bind a given address and port, so when a stale debug session still holds it the new inspector start fails and the debugger cannot attach.

The Fix

Kill the stale process or choose a distinct port with –inspect-port/–inspect, and add a script that selects an available port to avoid collisions in scripts and CI.

Watch out: An inspector bound to 0.0.0.0 exposes a debugger to the network; always bind 127.0.0.1 outside local development.

# find and stop the stale debug session
lsof -ti :9229 | xargs -r kill

# start on an explicit free port
node --inspect=127.0.0.1:9230 --inspect-brk ./server.js

# verify the target is listed
curl -s http://127.0.0.1:9230/json/list | head

Verify and Prevent

Start the app with the new port, open the inspector URL, and confirm the process appears in the target list; set a breakpoint to prove attach works.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.