ブログ一覧

astro dev がエラーも出さず死ぬ — Astro 7 の AI エージェント検出と ASTRO_DEV_BACKGROUND

Astro 7 のプロジェクトで astro dev を起動したら、こんな出力だけを残して死にました。

{"message":"Dev server process exited before becoming ready.","label":"SKIP_FORMAT","level":"error"}

スタックトレースなし。原因の手がかりゼロ。しかも同じコマンドを人間がターミナルで叩くと普通に詳細なエラーが出る。何が起きているのか調べたら、Astro 7 の新機能「AI エージェント検出」が原因でした。

本記事では、この仕組みと、本当のエラーを表示させる方法(ASTRO_DEV_BACKGROUND=1)、あわせて踏んだ Node.js バージョンの罠をまとめます。

前提: Astro 7.0.7 で確認しています。Claude Code などの AI コーディングエージェント経由で astro dev を起動するケースが対象です。

Astro 7 は「エージェントに起動されたか」を検出する

Astro 7 の dev コマンドは、起動元が AI エージェントかどうかを am-i-vibing というパッケージで検出します。実装はこうなっています(astro/dist/cli/dev/index.js)。

import { detectAgenticEnvironment } from "am-i-vibing";

function isRunByAgent() {
	try {
		return detectAgenticEnvironment().type === "agent";
	} catch {
		return false;
	}
}

// ...
const agentDetected = !process.env.ASTRO_DEV_BACKGROUND && isRunByAgent();
if (agentDetected) {
	flags.json = true;
}
// ...
if (flags.background || agentDetected) {
	// バックグラウンドモードへ
}

エージェントと判定されると、自動的にバックグラウンドモード + JSON 出力に切り替わります。意図としては親切な機能です。エージェントが dev server をフォアグラウンドで起動してターミナルを掴んだまま固まる、という定番の事故を防いでくれます。

問題は失敗時です。バックグラウンドモードは dev server を切り離した子プロセスとして起動するため、子プロセスが起動中にクラッシュすると、その stderr はどこにも表示されず、親は冒頭の「exited before becoming ready」という一行だけを返します。起動失敗の原因(モジュール解決エラー、設定ミス、ポート衝突…)が全部この一行に丸められます。

解決: ASTRODEVBACKGROUND=1 で通常モードを強制する

検出ロジックを見ると、環境変数 ASTRO_DEV_BACKGROUND が設定されていればエージェント検出自体がスキップされます。

ASTRO_DEV_BACKGROUND=1 astro dev

これで従来どおりフォアグラウンドで起動し、本当のクラッシュ理由がそのまま表示されます。エージェント環境で「astro dev が理由も言わず死ぬ」ときの調査は、まずこれです。

実際に隠れていたエラー: Node.js 22.15 未満

今回このモードで表面化したのは、これでした。

The requested module 'node:module' does not provide an export named 'registerHooks'

Astro 7 / Vite 8 のツールチェーンは node:moduleregisterHooks を使っており、これは Node.js 22.15.0 で追加された API です(Node.js 22.15.0 リリースノートの SEMVER-MINOR: module: implement module.registerHooks())。環境の Node が 22.14 だったため、dev server が起動プロセスの途中で即死していました。Node を 22.15 以降に上げて解決です。

「Node 22 系なら大丈夫」という思い込みは通用しません。同じメジャーバージョン内のパッチ差で ESM の named export が存在しないという、なかなか気づきにくい死に方をします。

おまけ 1: バックグラウンドモードは専用サブコマンドで管理する

Astro 7 のバックグラウンドモードには管理用サブコマンドが用意されています。

astro dev status          # 起動しているか確認
astro dev logs --follow   # バックグラウンド dev server のログを見る
astro dev stop            # 停止

エージェント検出でバックグラウンド起動された server も、これらで面倒を見られます。「ログが見えない」ときは astro dev logs が正道です。

おまけ 2: pkill -f "astro dev" は自分を殺す

dev server を止めようとして pkill -f "astro dev" を実行すると、pkill を実行しているシェル自身のコマンドライン引数にも "astro dev" が含まれるため、pkill が自分自身(の属するプロセス)にマッチして即死します(exit code 144 など、何も殺せていないのに終了する)。

astro dev stop を使うのが一番ですが、ポートで殺す方法も確実です。

PIDS=$(lsof -ti:4321); [ -n "$PIDS" ] && kill $PIDS

まとめ

  • Astro 7 は am-i-vibing で AI エージェント起動を検出し、自動でバックグラウンド + JSON モードに切り替える。起動失敗時のエラーが「exited before becoming ready」の一行に丸められる
  • ASTRO_DEV_BACKGROUND=1 を付けるとフォアグラウンド起動になり、本当のエラーが見える
  • Astro 7 / Vite 8 は module.registerHooksNode.js 22.15.0 で追加)を使う。Node 22 系でもパッチが古いと起動できない
  • バックグラウンド dev server の管理は astro dev status / logs / stoppkill -f "astro dev" は自分にマッチして死ぬ

参考リンク