ANTIGRAVITY LABEN
記事一覧/Antigravity 基本
Antigravity 基本/2026-04-29中級

Antigravity の AI エージェントが開発サーバーを再起動するたびに EADDRINUSE エラーになる問題の根治ガイド

Antigravity でエージェントに任せて開発を進めていると「EADDRINUSE: address already in use :::3000」が頻発する問題。原因はターミナル管理・ゾンビプロセス・HMR クラッシュの3つに集約されます。私が現場で使っている診断フローと恒久対策をまとめました。

antigravity435eaddrinuseporttroubleshooting88dev-server2

Error: listen EADDRINUSE: address already in use :::3000」という赤い文字列を、1日に何度も見ていませんか。Antigravity でエージェントに修正を任せながら開発していると、なぜか普段の VS Code 作業の倍以上の頻度でこのエラーに出くわします。私自身、Next.js のプロジェクトを Antigravity で半日触っただけで、lsof -i:3000 | xargs kill を5回以上叩いていることに気づき、これは何かおかしいと感じたのが調査のきっかけでした。

このエラー自体は OS レベルの「すでに誰かが同じポートを使っている」という単純な合図です。問題なのは、Antigravity でエージェントを使った開発フローに 構造的な3つの落とし穴 があり、それが連鎖的にゾンビプロセスを生み出してしまうことです。ここでは私が試行錯誤の末に整理した原因の切り分けと、エージェントに同じエラーを繰り返させない恒久的な対策をご紹介します。

なぜ Antigravity でだけ EADDRINUSE が頻発するのか

通常のエディタで開発しているとき、開発サーバーを止めるのは自分自身です。「Ctrl+C を押して、確認してから次のコマンドを叩く」という習慣で、ポートが二重に握られることはほとんどありません。

ところが Antigravity のエージェントは、自分が起動したプロセスを「自分のターミナルで自分が止めるべきもの」と認識しないことがあります。エージェントは新しい指示が来ると、別のターミナルタブを開いて npm run dev を打ち直すことが多く、結果として古いサーバーが裏で生き続けてしまいます。これが構造的な原因の入り口です。

具体的には、次の3つのパターンが繰り返し起きます。

  • タブ切り替え型のゾンビ化: エージェントが古いタブを閉じずに新しいタブで再起動する
  • バックグラウンド実行の取り残し: &nohup を使った起動が、ターミナル終了後も残る
  • HMR クラッシュ後の握り直し失敗: ホットリロード中の例外で、ポートだけ握られた状態の Node プロセスが残る

それぞれ対処法が異なるので、まず自分がどのパターンに当たっているかを切り分けます。

原因1: エージェントが古いタブを閉じずに別タブで再起動している

最も多いパターンです。エージェントに「ポートを 3000 から 4000 に変えて再起動して」と頼んだ直後、ターミナルパネルを下にスクロールすると、古い npm run dev が動いているタブがそのまま残っているのを見つけることがあります。

確認するには、ターミナルパネル右上のドロップダウン(または Cmd+Shift+P から Terminal: Show All Terminals)で、現在開かれているターミナルセッション一覧を表示します。dev と書かれたタブが2つ以上あれば、これが原因です。

すぐ効く対処

# 1. 現在 3000 番を握っているプロセスを特定
lsof -i:3000 -t
 
# 2. プロセスを優しく止める(推奨)
kill -15 $(lsof -i:3000 -t)
 
# 3. 30秒待って解放されなければ強制終了
sleep 30 && kill -9 $(lsof -i:3000 -t) 2>/dev/null
 
# 期待する出力: なし(コマンドが空で返れば解放成功)
lsof -i:3000

-15(SIGTERM)で先に試すのは、Next.js や Vite が graceful shutdown でファイルロックを正しく解放するためです。いきなり -9 を叩くと、.nextnode_modules/.cache 内に書きかけのバイナリファイルが残り、次回起動時に別のエラーを引き起こすことがあります。

恒久対策: AGENTS.md でエージェントの再起動手順を明示する

プロジェクトルートに AGENTS.md を作り、再起動の作法をエージェントに明示しておくと、二重起動の発生率がぐっと下がります。

# 開発サーバー操作のルール
 
## サーバー起動前に必ず実行
1. `lsof -i:3000 -t` で現在の使用状況を確認する
2. プロセスが見つかった場合は `kill -15 $(lsof -i:3000 -t)` で停止する
3. 5秒待ってから `npm run dev` を起動する
 
## サーバー停止時
- 既存の `npm run dev` タブを閉じてから別タブを開く
- 別タブで再起動する場合は、必ず古いタブの停止を確認してから

私が運用している Dolice Labs の 4 サイトでは、この AGENTS.md を入れてからエージェント起因の EADDRINUSE が体感で 8 割減りました。

原因2: ターミナルが閉じてもプロセスが残るバックグラウンド実行

「サーバーを起動してそのまま別の作業をさせて」と頼むと、エージェントは npm run dev & のようにバックグラウンド実行で逃がしてしまうことがあります。これをやられると、Antigravity を再起動しても親プロセスから切り離された Node プロセスが OS に残り、再起動直後の最初のコマンドが必ず EADDRINUSE で落ちます。

全プロセスを横断的に確認する

特定のポート番号がわからない時のために、Node プロセスをすべて洗い出すワンライナーを覚えておくと便利です。

# Node プロセスをポート付きで一覧
ps aux | grep -E "node|next|vite" | grep -v grep
 
# まとめてクリーンアップ(注意: 他のプロジェクトの dev も止まる)
pkill -15 -f "next dev"
pkill -15 -f "vite"
 
# 期待する出力: 何も表示されなければ完全に停止している
lsof -i -P | grep LISTEN | grep node

pkill -f の正規表現は意外と緩いので、pkill -15 -f "node" のような書き方は別プロジェクトの長時間バッチを巻き込むことがあります。プロセス名は最低でも next devvite のようにフレームワーク固有の文字列を含めるのが安全です。

エージェントに & を禁止する

AGENTS.md に以下を追記しておきましょう。

## 禁止する起動方法
- `npm run dev &`(バックグラウンド実行)
- `nohup npm run dev`(端末切断後も残る起動)
- `disown` / `screen` / `tmux` を経由した永続化
 
長時間動かしたいプロセスは、必ずフォアグラウンドで起動し、専用ターミナルタブを残して指示を続けてください。

原因3: HMR クラッシュ後のゾンビプロセスが残留する

3つ目はもっとも厄介で、エージェントが悪いわけではないケースです。Vite や Next.js の Hot Module Replacement が大規模なリファクタの直後に内部例外で落ちると、メインの Node プロセスは終了したように見えても、ポートを握っていた子プロセスが残ることがあります。

これは macOS の Activity Monitor を開いても気づきにくく、lsof で初めて発覚します。

# ポート別にプロセスツリーごと表示
lsof -i:3000 -P
# 例: node    91234  user   24u  IPv6  0xabc...  0t0  TCP *:3000 (LISTEN)
 
# プロセスツリーを確認(macOS)
pstree -p 91234
 
# 同様に Linux
ps -ef --forest | grep 91234

子プロセスが残っている場合は、プロセスグループ単位で止めるのが確実です。

# プロセスグループ ID を取得
PGID=$(ps -o pgid= -p 91234 | tr -d ' ')
# プロセスグループごと停止
kill -15 -- -$PGID
 
# 期待する動作: 子プロセスを含む dev サーバーがすべて停止

恒久対策: 開発サーバーをポート競合に強くする

そもそもポートが衝突しても自動で別のポートに逃げてくれれば、エラー自体が事故ではなく「ちょっとした通知」になります。Next.js の場合は package.json を以下のように変更します。

{
  "scripts": {
    "dev": "next dev -p 3000 --turbo || next dev -p 0 --turbo"
  }
}

-p 0 は「OS に空きポートを割り当てさせる」という指定で、3000 番が埋まっていても自動で別のポートで起動します。Vite なら vite.config.ts で同じことができます。

// vite.config.ts
import { defineConfig } from "vite";
 
export default defineConfig({
  server: {
    port: 3000,
    strictPort: false, // ← これが重要
  },
});

strictPort: false にしておくと、3000 番が埋まっていれば 3001、3002 と順に空きを探します。strictPort: true のままだとそのまま EADDRINUSE で落ちる仕様なので、Antigravity でエージェントに任せる開発では false 推奨です。

即座にポートを解放するための起動前スクリプト

毎朝の作業開始時に走らせる「お掃除スクリプト」を作っておくと、心理的に楽になります。私は scripts/dev-clean.sh として保存しています。

#!/usr/bin/env bash
# scripts/dev-clean.sh
# 開発でよく使うポートを掃除してから起動するヘルパー
set -euo pipefail
 
PORTS=(3000 3001 4000 5173 8000 8080)
 
for PORT in "${PORTS[@]}"; do
  PIDS=$(lsof -ti:$PORT 2>/dev/null || true)
  if [ -n "$PIDS" ]; then
    echo "🧹 port $PORT を解放中(PID: $PIDS)"
    kill -15 $PIDS 2>/dev/null || true
    sleep 1
    # 残ったら強制終了
    REMAIN=$(lsof -ti:$PORT 2>/dev/null || true)
    [ -n "$REMAIN" ] && kill -9 $REMAIN 2>/dev/null || true
  fi
done
 
echo "✅ 全ポート解放完了。dev サーバーを起動してください"

実行権限を付けて、package.json に登録します。

{
  "scripts": {
    "dev:clean": "bash scripts/dev-clean.sh && npm run dev"
  }
}

エージェントへの指示も npm run dev ではなく npm run dev:clean を使うように AGENTS.md に書き加えれば、起動の度に自動でクリーンになります。

関連記事

トラブルシューティングの隣接領域として、次の記事も合わせてご覧いただくと役立つはずです。

まずは「次の dev 起動前に lsof を1回叩く」習慣から

EADDRINUSE は単発で見ると単なるエラーですが、Antigravity でエージェント開発をしている限り、構造的に再発しやすい問題です。今日試していただきたいのは1つだけ、npm run dev を打つ前に lsof -i:3000 を打つ習慣を1日続けてみてください。「なんとなく毎回起動が失敗する」という曖昧な不快感が、「今、何が起きているか」が見える状態に変わるはずです。そこから先は、本記事の対策を1つずつ取り入れていけば、エージェントとの開発リズムが目に見えて軽くなっていきます。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Antigravity 基本2026-05-31
Antigravity のエージェントが途中で 429 RESOURCE_EXHAUSTED と出して止まるときの原因と対処
Antigravity でエージェントに長いタスクを任せていると、途中で「429 RESOURCE_EXHAUSTED」と出して手が止まることがあります。これは API のレート制限・クォータ超過のサインです。私が自動運用の現場で踏んだ原因の切り分けと、再発させないための具体的な対処をまとめました。
Antigravity 基本2026-05-28
Antigravity の Google サインインが認証画面から戻らないときの原因と対処
Antigravity 起動直後に Google サインインを押したあとブラウザが回り続けてエディタ側に戻ってこない、という症状に何度も振り回されてきました。コールバックポート・サードパーティ Cookie・古いセッションファイル・プロキシの4観点で切り分け、確実に復帰させる手順をご紹介します。
Antigravity 基本2026-05-25
Antigravity の Agent が ssh / sudo / git rebase -i で固まる:TTY 不在問題の診断と恒久対策
Antigravity の Agent に作業を任せていると ssh・sudo・git rebase -i のようなインタラクティブコマンドで突然画面が止まる。原因は Agent のターミナルが PTY を割り当てない点にあります。診断手順と私が現場で使っている恒久対策をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →