Nuxtのdevサーバーがheap out of memoryで落ちた原因:再現動画のシーン分割読み込みと終わらない回帰テスト

開発eurekapu-nuxt4

Nuxtのdevサーバーがheap out of memoryで落ちた原因:再現動画のシーン分割読み込みと終わらない回帰テスト

朝、Google Tasks に期日切れのタスクが1つ残っていた。 「Excel基礎講座 章2(ショートカット講座からの移行計画)」で、期日は前日の9/25。 まずレビューして、内容に問題がなければ実装しようと、07:13 に開いたセッションの Claude Code に頼んだ。

調べてもらうと、レビューも実装もすでに済んでいた。 残っていたのは本番デプロイだけで、Google Tasks を完了にし忘れていただけだった。 タスクはここで片付くはずだった。

起動から約2分で落ちていた dev サーバー

Claude Code は章2を確かめるために :3200 で dev サーバーを立て、報告に「dev サーバーは起動したまま」と書いていた。 これは誤りだった。 dev サーバーは起動から約2分で JavaScript heap out of memory を出して落ちていた。 Node の上限は4GBだった。 章2の確認(動画4本の読み込み、基本ショートカット一覧の表示、コンソールエラーなし)は落ちる前に済んでいたので、確認の結果は変わらない。

「もうメモリー落ちちゃったんですか?」と聞き返して、何が起きているのかを調べてもらった。 アイドル時のメモリは1.4GB(起動直後の山は2.7GB)で落ち着いていた。

原因は、章2のページではなかった。 並行セッションが再現動画の台本(app/utils/excelScenes/)を保存するたびに、dev サーバーがファイルの読み込みと組み立てをやり直し、メモリを大量に使っていた。 保存が何度か重なったところで、上限の4GBを超えて落ちていた。 PC 全体の空きは約12GBあり、マシンのメモリが足りなかったわけではない。

分割すれば済むのか

自分は、これはリファクタリングが要る話だと受け取った。 ある程度分割してやればいいのか、そうでもないのか。 根本の対策をやるほうがいいとは思った。 ただ、まず考えを聞かせてもらい、その内容でよいか Codex のレビューも受けておくよう頼んだ。

Claude Code は計画書 memo/2026-09-26/excel-scene-dev-memory-plan.md を書き、Codex にレビューさせた。 判定は「条件付き承認」で、致命的な指摘が1点あった。 その点は計画書の側で直し、Claude Code 自身も「方針はこのままで進めてよい」と判断していた。 自分は y で進めた。

Claude Code は、予告していたメモリの計測を、並行セッションの邪魔になるとしていったんやめていた。 向こうのセッションが止まったと伝えると、残りは計測とコミットだけだという。 台本の中身は変えずに保存時刻だけを更新し、保存を10回再現して測ってもらった。

根本対策の第一弾は、コミット 42457103 に入った。 中身は API の移設、nuxt.config.ts、package.json、計画書、issue である。 台本を保存しても、dev サーバーのメモリはほぼ増えなくなった。

ところが、コミット前の lint とテストが5分を超えても終わらない。 最後のテストは15分以上終わらず、Claude Code が止めた。

15分で終わらない回帰テスト

テストが終わらない理由がよくわからなかったので、原因を調べてもらった。 カメラのテストは6秒で通った。 残るのは回帰テスト excelSceneBookRegression.test.ts だった。

固まっているのか、それとも今日の変更で遅くなったのか。 並行セッションも同じテストを調べていて、向こうが起動した vitest(08:15:30 起動)は止めたと連絡をくれた。 両方の調べを合わせた結論は「固まってはいない」だった。 もともと数十分かかる重いテストで、15分で止めていただけだった。

この回帰テストは、21本×2通りの全コマを、1コマごとに頭から計算し直す作りになっている。 1本あたり30〜40秒かかるので、全体で20〜30分かかっても不思議ではない。 何をやっているテストなのかを説明してもらい、そのうえで1本だけ回してもらった。

ほかに何も走らせずに cfws-step1 の1本だけを測ると、変更前が30.5秒、変更後が32.0秒だった。 差は約5%で、ぶれの範囲に収まる。 計算した画面も、変更前と変更後の両方で記録と完全に一致した。 途中で出ていた「31.2秒→43.5秒」という数字は、テストが2つ同時に走っていて膨らんだものだった。

この結果を issue に追記して、コミット f55d9b4c に入れてもらった。 このコミットも、Codex のレビューを通らないまま入った。

Codex が 401 を返し続けた朝

この日の朝、Codex は障害で止まっていた。 障害を突き止めたのは、07:11 に開いた別のセッションである。 そちらでコミット 6614e23f を作ったとき、コミット時の Codex レビューが動かないまま通っていた。

Codex の認証を取り直そうと、どのコマンドだったかを聞いた。 そのセッションの Claude Code の見立ては、ChatGPT のログインは正常なのに、Codex が sk-svcac… で始まるサービスアカウント用の API キーで接続しようとして弾かれている、というものだった。 自分は入力欄から codex login を打ったが、「Login cancelled」で終わった。 コードを入力する方式を勧められ、PowerShell 経由でログインし直した。

それでも直らない。 Claude Code が順に疑ったのは、mise、Windows の資格情報マネージャー(項目名だけを見て、中身は見ない)、PowerShell からの起動、codex doctor だった。 どれも原因ではなく、どのモデルでも同じエラーが出た。 最後に OpenAI 公式の稼働状況ページを見ると、「Codex down due to 401 backend key error」(対応中)が出ていた。 問題の API キーは、OpenAI のサーバーが内部で使っている鍵で、自分が設定したものではなかった。 その鍵が壊れていて、どのモデルでも、どの端末から起動しても 401 になっていた。

ほかのセッションもコミットで引っかかるはずなので、メッセージを投げておいてもらった。 送り先は eurekapu-nuxt4-0c と mdx-playground-8b の2つで、コミットは止まらずに Codex のレビューなしで通ること、ログインのし直しは要らないことを伝えた。 07:13 のセッションの 42457103 も、この障害でレビューなしで入っている。 07:11 のセッションでは次のコミット fd42722b もレビューなしで通り、復旧したら 6614e23f と fd42722b をあらためてレビューにかける、という申し送りが残った。

章2を本番に出す

回帰テストの件は大体OKなので、デプロイまで進めるよう指示した。 Claude Code は R2 に上げる25件の一覧を最終確認し、並行セッションに一言伝えてからアップロードした。 25件すべて成功し、本番から実際に取れることを確かめてから、7分ほどのデプロイに入った。

本番では章2の動画が読み込まれ、読み上げの再生も 0:13 / 1:10 まで進んだ。 第3章の再現動画も確かめてもらい、Google Tasks の章2のタスクもここで完了にしてもらった。

そのあと、章2の目次をパソコン幅で3段表示に変えた。 この講座のビューアーには、全チャプターの中身を常時展開する表示と、セクション/チャプター/トピックの3段表示があり、ページごとに切り替えられる。 キーボードショートカットのページの1行を変えるだけで済んだ。 再生ボタンの左の空きも詰め、あわせてコミット 8c279096 に入れた。

開いたシーンの分だけ読み込む(Step 2)

第一弾で、保存のたびに膨らむ問題はつぶれた。 ただ、完全な解決ではない。 再現動画のページ(/dev/excel-scene)を初めて開いたときだけ、メモリが一時的に3.0GBまで上がる。 ページが全シーンを、ブックのデータ約7MBごと読み込んでいるためだ。 いまの上限の8GBには収まるが、余裕を広げるには Step 2(開いたシーンの分だけ読み込む)が要る。 自分はこれに着手してもらい、それまでの変更の本番デプロイとコミットもあわせて任せた。

本番デプロイは先に済ませた(09:08)。 ビルドの間だけ dev サーバーを止めるので、並行セッションには先に一言伝えてもらった。

Step 2 は、SCENES の本体を書き換えるところから始まった。 書き換えたあとも、全57シーンの定義は書き換え前と完全に一致した。 次に、開いたシーンだけを読み込む入口を作り、テストは67件すべて通った。 最後に dev ページを新しい入口に切り替えた。

初めて開いたときの dev サーバーのメモリの山は、3.0GBから2.0GBに下がった。 コミットは 12062f6d で、Codex の指摘はなかった。 朝に思い浮かべた「分割」は、ここで読み込みをシーンごとに分ける形になった。

触る前にひとこと伝える

Step 2 のあとは、並行セッションとの受け渡しが続いた。 自分の指示を受けて bookScene.ts と excel-scene.vue を触る、と向こうから連絡が来た。 xlookup のシーンで台本と音声の時刻が食い違い、プレビューのページが500エラーになる件を直すという。 07:13 のセッションは、向こうが終わるまでその2ファイルに触らないと返した。

編集が終わると、今度は向こうから xlookup の不具合を直してほしいと頼まれた。 07:13 のセッションは、関数の活用の台本(段⑥)は担当外だとして引き受けず、判断を自分に回してきた。 結局、自分が了承して、向こうのセッションが直した(2bfb1708)。 カメラ欄の組み替え(e01f625c)とあわせ、2件とも Step 2 の 12062f6d の後に積まれていた。

その後、PC の空きメモリが約4.9GB(全体32GB)まで減り、07:13 のセッションが dev サーバーの起動に使ったシェルを、Claude Code 本体が自動で止めた。 dev サーバー本体(約0.9GB)は応答を続けていた。

API が落ちても戻るようにする

画面が表示されないと自分が言ったので、並行セッションが :3200 の dev を起動し直し、その経緯を報告してきた。 その報告から、07:13 のセッションが作った再現動画の API サーバーの仕組みに、弱点が見つかった。 向こうでもう直したように見えたので、本当にこちらの修正が要るのか確認し直させた。

その確認の途中で、事故が起きた。 10:37ごろ、07:13 のセッションは検証用に別ポート(3292)で API サーバーを立て、本体だけを止める実験をした。 このとき PID を取り違え、並行セッションの dev の API サーバー本体を止めてしまった。 約1分、:3200 のプレビューの API が502を返した。 07:13 のセッションは、保存時刻だけを更新して node --watch に起動し直させ、200に戻したうえで向こうに報告を入れている。

構成は、nuxt → dev の本体 → 見張り役 → API 本体の順になっていた。 API 本体だけを止めて確かめ直すと、並行セッションの修正と今回の問題は別の場面を扱っていた。 こちらの修正はまだ要る。

自分が了承して、modules/excel-scene-dev-server.ts に見張りを足してもらった。 3秒おきに API のポートへつなぎ、3回続けて(約9秒)つながらなければ、node --watch と API 本体を木ごと止めて起動し直す。 5分のうちに5回を超えたら、ループしないように見張りを止める。 コミットは b9b404ac で、API が落ちても約10秒で自動的に戻るようになった。

最後に、このセッションの詰め残しを聞いた。 残っていたのは origin への push だけだった。 進捗は計画書、issue、章2の実装記録の3つに書き込み、9573ec7c にコミットしてもらった。

段⑥は進んでいなかった

08:59 のセッションでは、Google Tasks の「関数の活用 段⑥」の状況を確かめてもらった。 タスクのメモには、先ほどのデプロイで再現動画18本が R2 と本番に載ったので一部は進んでいるかもしれない、と書いてあった。 計画書 memo/2026-09-24/functions-restructure-plan.md の §12-2 と突き合わせると、段⑥は手順1の「19本のプレビュー確認」で止まっていた。 本番に出た18本は、この19本とは別の組1〜3bだった。 タスクそのものは進んでいない。

学び

  • dev サーバーが落ちた原因は、見ていた章2のページではなく、並行セッションの台本保存だった。落ちた瞬間に開いていたページより先に、何がファイルを書き換えているかを見る。
  • 「31.2秒→43.5秒」という遅くなったように見える数字は、同時に走った2本のテストが作っていた。1本だけを単独で回すと30.5秒と32.0秒で、変更の影響はぶれの範囲だった。
  • Codex の 401 は、手元の設定をいくら掘っても原因が出てこなかった。公式の稼働状況ページを開いたところで、OpenAI 側の障害と分かった。
#Claude Code#Nuxt#メモリ不足#devサーバー#Vitest#Codex#並列セッション#Excel講座