エラーの内容
Error: listen EADDRINUSE: address already in use :::3000
at Server.setupListenHandle [as _listen2] (node:net:1739:16)
at listenInCluster (node:net:1787:12)
at Server.listen (node:net:1875:7)
at Function.listen (/app/node_modules/express/lib/application.js:635:24)
ポート 3000 がすでに使用中です。Node.js がそのポートにリスナーをバインドしようとしたところ、別のプロセスがすでに起動していたため、処理を中断しました。同一のTCPポートを2つのプロセスが共有することはできないため、どちらか一方を終了させる必要があります。
原因
よくある原因は3つあります:
- 以前のサーバーインスタンスがクラッシュした、またはターミナルウィンドウを強制終了した。Node.js プロセスがバックグラウンドで動き続け、ポート 3000 を保持したままになっている。
- 別のプロセスがすでにそのポートを使用している — 別の Node.js アプリ、Webpack dev server、Python Flask アプリなど、さまざまな可能性がある。
- 再起動が早すぎた。旧プロセスが終了した後、OSがポートを解放するまでに少し時間(通常は数秒)が必要です。Ctrl+C の直後に
npm startを実行すると、その猶予時間より早く起動しようとしてしまうことがある。
手順を追った解決方法
ステップ1:ポートを使用しているプロセスを見つける
macOS / Linux の場合:
lsof -i :3000
出力例:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 1234 alice 23u IPv6 12345 0t0 TCP *:3000 (LISTEN)
PID 列の値(ここでは 1234)が、次のステップで必要になります。
ss や netstat を使う場合も同様に使えます:
# ss を使う場合
ss -tlnp | grep :3000
# netstat を使う場合
netstat -tlnp | grep :3000
Windows(コマンドプロンプトまたは PowerShell)の場合:
netstat -ano | findstr :3000
出力例:
TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 5678
最後の数字(5678)が PID です。
ステップ2:プロセスを終了する
macOS / Linux の場合:
kill -9 1234
1234 の部分を実際に確認した PID に置き換えてください。あるいは、調べる手間を省いて一発で実行することもできます:
kill -9 $(lsof -ti :3000)
Windows(管理者として実行)の場合:
taskkill /PID 5678 /F
ステップ3:Node.js サーバーを再起動する
node app.js
# または
npm start
# または
npx ts-node src/index.ts
別の解決策:別のポートを使う
ポート 3000 を使用しているプロセスが意図的なもので、そのアプリも動かしておく必要がある場合は、サーバーを別のポートに移動するだけで解決します。
アプリのコードを変更する場合:
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`サーバーがポート ${PORT} で起動しました`);
});
コードを変更せずに起動時にポートを指定する場合:
PORT=3001 node app.js
Windows の場合:
set PORT=3001 && node app.js
nodemon / 開発用ウォッチモードでの解決方法
ファイルを保存するたびにこのエラーが発生する場合、nodemon がOSのポート解放前にプロセスを再起動している可能性があります。1秒の遅延を設定するだけで通常は解決します:
# nodemon.json
{
"delay": 1000
}
それでも解決しない場合は、すべての Node プロセスを強制終了してからやり直してください:
# macOS / Linux — 全 Node プロセスを終了
pkill -f node
# その後、再起動
npm run dev
修正の確認方法
プロセスを終了した後、同じ検索コマンドを実行して確認します:
# macOS / Linux
lsof -i :3000
# Windows
netstat -ano | findstr :3000
何も出力されなければ、ポートは解放されています。サーバーを起動すれば、問題なく立ち上がるはずです。
実際に応答しているか確認したい場合は、curl で簡単にテストできます:
curl http://localhost:3000
# またはブラウザで http://localhost:3000 を開く
このエラーを防ぐためのヒント
- ターミナルを閉じるより Ctrl+C を使う — ウィンドウを閉じると Node.js プロセスが孤立したまま残ることがよくあります。プロセスは動き続け、ポートを占有し続けます。Ctrl+C は SIGINT を送信し、正しく終了処理を行います。
- ポートは環境変数から読み込む —
3000のハードコードは問題が起きるまでは便利ですが、process.env.PORT || 3000にしておけば、コードを編集せずに環境変数一つでポートを切り替えられます。 - 本番環境ではグレースフルシャットダウンハンドラを追加する — これにより、終了時にサーバーがポートを正しく解放できます:
process.on('SIGTERM', () => {
server.close(() => {
console.log('サーバーを終了しました');
process.exit(0);
});
});
- PM2 を使う場合は古いインスタンスに注意する —
pm2 restart appはオーバーラップを自動で処理します。クリーンな状態から始めたい場合は、まずpm2 stop allを実行して、ポートを占有しているプロセスが残っていないことを確認してください。

