Node.js で「EADDRINUSE: address already in use」が解消できない
EADDRINUSE は同じポートで他プロセスが LISTEN していることが原因。
lsof / netstat で占有プロセスを特定して終了するか、ポート番号を変更すれば解決する。
公開: 更新:
要約
Error: listen EADDRINUSE: address already in use :::3000 のエラーは、同じポートを既に別のプロセスが占有しているために発生する。lsof -i :3000 でプロセスを特定して終了する、もしくはポート番号を変更すれば解決する。
よくある原因
- 直前のプロセスが残っている: ターミナルで Ctrl+C を押したつもりが Node プロセスが孤児化して残っている。
- 別アプリが同ポートを使用している: 例えば 3000 は React dev サーバ、5432 は PostgreSQL など、他開発ツールとぶつかる。
- コンテナ / WSL のポートフォワード: Docker Desktop の published ports が解放されておらず、ホスト側の同番ポートを掴み続けている。
- TIME_WAIT 状態: 直前にサーバが落ちたあと、TCP が TIME_WAIT で数十秒〜数分占有を続ける。
解決策
1. 占有プロセスを探して終了する
macOS / Linux:
lsof -i :3000
# または
ss -ltnp | grep :3000
kill -9 <pid>Windows (PowerShell / cmd):
netstat -ano | findstr :3000
taskkill /PID <pid> /FNode.js のシステムエラー一覧(新しいタブで開く) に EADDRINUSE の記載がある。
2. ポート番号を変える
環境変数で切り替える形にしておくと衝突時に楽。
const port = process.env.PORT ?? 0; // 0 を渡すと OS が空きポートを割り当てる
server.listen(port, () => {
console.log("listening on", server.address().port);
});0 を渡すと OS が任意の空きポートを選ぶので CI などで便利(net.Server.listen の公式ドキュメント(新しいタブで開く) を参照)。
3. Docker Desktop / WSL の再起動
ホストで別プロセスが見当たらないのに EADDRINUSE が出る場合、Docker / WSL のポートフォワードが残っていることが多い。
Docker Desktop を再起動するか、wsl --shutdown を実行する。
4. TIME_WAIT 状態の回避
短時間で再起動を繰り返すスクリプトでは、前回終了時に server.close() を確実に呼ぶか、ポート 0 を使い回す。
Linux なら net.ipv4.tcp_tw_reuse=1 で TIME_WAIT を再利用できる場合がある。
実行例
実際に上記の手順を node:20(Debian GNU/Linux 12 bookworm)環境で動かすと、PORT=3000 を二重に bind しようとした2つ目のプロセスが listen EADDRINUSE: address already in use :::3000 を出力して終了コード 1 で終了し、PORT=3001 に切り替えた3つ目のプロセスは終了コード 0 で正常に起動したことが確認できる。
$ PORT=3000 node server.js
listening on 3000$ PORT=3000 node server.js
listen error: EADDRINUSE listen EADDRINUSE: address already in use :::3000
2 つ目の終了コード: 1$ PORT=3001 node server.js
listening on 3001
別ポートの終了コード: 0
1 つ目の終了コード: 0— 2026-08-02 時点の出力