【非エンジニアが挑む】Could not find a production buildの正体|メモリ不足を疑ったら原因は別だった

「Could not find a production build」の正体|メモリ不足を疑ったら原因は別だったの構成

前回の記事で、対局が一瞬で終わり続けるバグの原因を特定し、修正することができました。

前回の記事

あとはこれをVPSに反映するだけ!!

Tomoya

そう思っていたのですが、またしてもにぶつかることになりました。


目次

おさらい:修正はGitHubにpushしただけでは反映されない

Tomoya

本題に入る前に、一つだけ思い出しておきたいことがあります!

ローカルのCursorでコードを修正しても、それをGitHubにpushしただけでは、VPS上のプログラムは自動では更新されません

VPS側で自分からgit pullを実行して、初めて最新のコードが反映されます

しかもNext.js側の場合、コードを取得しただけでは足りず、npm run buildでビルドをやり直し、その上でpm2のプロセスを再起動する、というところまでやって、ようやく反映が完了します。

今回は、この一連の作業(push→pull→build→再起動)をすべて終えたつもりで、いざブラウザを開いてみたところから始まります。

ターミナルでgit pullコマンドを実行し、tsconfig.jsonやvps/openings.pyなどの変更ファイルが更新・同期された画面
ターミナルでgit pullを実行し、リモートリポジトリから更新されたファイルの差分情報を取り込んだ結果です。

症状:ページが真っ白、Could not find a production build

ブラウザを開いても、見えるはずの観戦画面がどこにも存在しない状態になっていました。

Tomoya

pm2 logsを確認すると、こんなエラーが延々と流れ続けています。

Could not find a production build in the '.next' directory.
Try building your app with 'next build' before starting the production server.

Next.js側は、主に画面表示を担当している部分です。定期的にPython側(チェスの対局エンジン)が書き出すデータを取得し、ブラウザの表示を更新し続ける、という役割で運用しています。そのため、まず表示を立ち上げるには、事前に「ビルド」という変換作業を通す必要があり、それが完了して初めて本番用のサーバーが起動する、という順番になっています。

チェス対局観戦システムの全体図。Pythonバックエンド、対局DB、Next.jsフロントエンド、ブラウザの連携フロー
Pythonによる対局エンジンとNext.jsによる観戦画面、対局DBが連携してブラウザへ情報を届けるシステム全体の構成図です。

今回、一見するとビルド自体は通っているように見えていました。赤いエラー表示もなく、このまま何事もなく起動するはずだと確信していたのに、実際に起動しようとするとエラーになる

Tomoya

これを見た瞬間は、「え、なんで?」という気持ちしかありませんでした。


最初の仮説:単純に反映し忘れただけでは?

Tomoya

人間、まず最初に思い浮かぶのは、自分の単純なミスです。

何かの手順を飛ばしてしまったのではないか、と考えました。

GitHub上に修正済みのファイルがあることを確認した上で、もう一度git pullをやり直し、差分をきちんと取得します。

git pull
npm install
npm run build

ビルド、ビルド、ビルドで、確実に反映させたつもりでした。

ここでも、はっきりと「エラー」と分かるような赤い表示は出ていません。「これなら大丈夫だろう」と思い、pm2を再起動してみましたが、状況はまったく変わりませんでした。

Tomoya

頭の中は「?」でいっぱいです。

??混乱する頭の中??

ちょっとコードを直しただけで、こんなことが起きるものなのか。

どこかでコンフリクトしている? pm2自体のバグ? 

自分の知らないところで何かが悪さをしているのではないかと、正直不安になりました。

ここでAIに助けを求めることにします。


[PR]:以下のリンクから始めると、初回1か月分が割引価格でCursorを利用できます。1か月使ってみて合わなければ、すぐに解約できる気軽さも魅力だと感じています。


echo $?という新しい武器を知る

AIに状況を伝えたところ、まず疑うべきはビルドの段階そのものだと指摘されました。

.nextが見当たらない」というエラーの背景には、いくつかの可能性がある
  • ビルド時にBUILD_IDというファイルが正しく発行されていない
  • そもそもpullした後にビルドをやり直していない
  • ビルドが別のディレクトリで実行されてしまっている
  • ビルドがメモリ不足などで失敗しているのに、ログの最後の方だけを見て「成功した」と勘違いしてしまっている
  • あるいは.nextを消すコマンドを誤って実行してしまった——などです。

そこで提案されたのが、直前に実行したコマンドが成功したか失敗したかを確認するという方法でした。

npm run build
echo $?

結果は「1」。

ターミナルで echo $? コマンドを実行し終了ステータスが 1(異常終了)であることを確認した画面
ターミナル上で「echo $?」コマンドを実行し、直前の処理が異常終了(終了ステータス 1)したことを確認しています。
Tomoya

これは失敗を意味する数字です。

これを見た時、自分がどこで失敗していたのか、まったく見当がついていなかったことに気づかされました。

赤いエラーログが出ていないからといって、成功しているとは限らない——この事実に、思わぬ落とし穴があるのだと痛感した瞬間でした。

この結果と、自分なりに考えた3つの仮説を、AIに報告することにしました。


3つの仮説を立てる

自分の頭で考えた仮説は、次の3つでした。

1.メモリ不足

契約している4GBプランのVPSには、すでに2つほど常駐しているプログラムがありました。そこにさらに2つ(Pythonの対局エンジンとNext.jsのサーバー)が加わったことで、メモリが足りなくなっているのではないか——非エンジニアなりに、まずここを疑いました

2.Node.jsのバージョン不足

システム全体で一貫性を保つには、バージョンをきちんと揃えておく必要があるはずです。

ローカルPCとVPSとで、Node.jsのバージョンにズレがあり、それが原因になっているのではないか

3.依存関係の不整合

バージョンと同じように、コードを修正したことで、各パッケージ同士の依存関係の噛み合わせが崩れてしまったのではないか

いずれも確信があったわけではなく、あくまで自分なりに考えた仮説に過ぎません

それでも、考えられる可能性を整理してAIに伝えることが、次の一歩につながりました。


メモリ不足を検証してみる

AIからの回答は、「4GBあれば、そう簡単には枯渇しないはず」というものでした。

それでも心配であれば、と確認の手順も示してもらえたので、実際に試してみることにしました。

dmesg | grep -i "killed process" ※未検証

これは、メモリ不足によって強制終了させられたプログラムがないかを確認するコマンドでしたが、権限の都合上、このVPS環境では実行が許可されておらず、使うことができませんでした

Tomoya

仕方がないので、今動いているメモリの使用状況だけを確認します。

free -h
free -hコマンドを実行しサーバーのメモリ使用量と空き容量を確認したターミナル画面
コマンドラインでfree -hを実行し、システムメモリの割り当て状況やキャッシュ、使用可能容量を確認している画面です。
Tomoya

メモリも2.8Giの表示を確認して、十分な余裕がありました。

もしこれでメモリ不足が判明した場合の対策として、「スワップ」という仕組みがあることも教えてもらいました。

足りなくなったメモリを、ディスクの一部を使って補ってくれる仕組みだそうです。

今回は結果的に使うことはありませんでしたが、こんなに心強い仕組みが用意されているのかと、単純に発見が嬉しかったです。振り返ってみると、VPS上で今どれくらいメモリを使ってシステムが動いているのかを、これまで一度も可視化して見たことがありませんでした。今回のトラブルのおかげで、初めてそこに目を向けるきっかけになったのは、思わぬ収穫だったと思います。


しかし、本当の原因は別だった

Cursorにさらに詳しく調査を依頼した結果、判明した原因は、まったく予想していないものでした。

tsconfig.jsonというファイルに入れていた"ignoreDeprecations": "6.0"という設定が、VPS側で使われているTypeScriptのバージョンでは無効な値として扱われてしまい、ビルドの「型チェック」という段階でエラーになっていた、というのが真相でした。

Tomoya

これを知った時は、正直なところ唖然としました!

この設定は、ローカルの開発環境(IDE)が出していた、baseUrlという項目についての非推奨警告を、ただ黙らせたいだけの理由で、ちょっとした機能追加のついでにAIへ依頼して入れてもらっていたものだったからです。

Tomoya

まさかこれが、今回の騒動の原因になるとは思ってもいませんでした。

今まで自分が追いかけていたチェス対局のロジックとは全く関係のない、ほんの小さな修正が、静かにビルドそのものへの道をふさいでいたのです。

おそらくCursorは、あくまでローカルの開発環境に向けて修正を行っただけで、VPS側の環境までは意識していなかったのだと思います。もしくは、VPS側にもローカルと同じ環境が存在している前提で判断していたのかもしれません。


「ローカルでは動くのにVPSでは動かない」の正体

結局、原因はメモリでも、Node.jsのバージョンでもありませんでした。IDEの警告を消すためだけに入れていた、たった1行の設定です。

この事実から思った事

今回は思いもよらない結末を迎えましたが、これも一つ、成長できた経験だったと思っています。

仮説を立てて、検証して、外れて、それでも諦めずに次の仮説に進んでいく

この一連の流れそのものが、必要なプロセスなのだと信じています。

ある意味では、今回もやはり「バージョンの不一致」が引き起こした問題であり、ローカルの開発環境とVPSのビルド環境との間に、ちょっとした相性の悪さがあった、ということになります。

修正方法はシンプルで、tsconfig.jsonから該当の設定を削除し、更新した上でもう一度ビルドとサーバーの起動をやり直しました。

tsconfig.jsonからignoreDeprecationsの設定行を削除するコード差分画面
tsconfig.jsonの編集画面にて、不要となったignoreDeprecationsの記述行を削除する変更プロセスを示しています。
npm run build
echo $?
pm2 restart chess-web

結果は「0」。

npm run build の成功ログと echo $? で終了ステータス 0(正常終了)を確認した画面
「npm run build」が成功し「Compiled successfully」と「echo $?」による正常終了コード「0」が出力されたターミナルです。

無事にブラウザを開くことができました。よし、という気持ちと、心底ほっとした安堵感が同時にやってきました。


まとめ・次回予告

Tomoya

これで、観戦システムがようやく安定して稼働する状態になりました!

ローカルでの実装から始まり、ここまでの一連の物語が、ひとまず完結です。

次回は、システム整備

次回は、このチェスシステムが安定して観戦できる状態を保てるよう、改修の計画を立てて実行していこうと考えています。

今回の一連のトラブルを通じて、見た目の面でも、システムの面でも、まだ整えるべき部分がいくつも残っていることに気づきました。次はそこを一つずつ整えていく記事を書いていきたいと思います。

次回予告「観戦システム、ついに安定稼働 安定稼働へ!Cursorと共に整備」の案内

以下のリンクから始めると、初回1か月分が割引価格でCursorを利用できます。1か月使ってみて合わなければ、すぐに解約できる気軽さも魅力だと感じています。

他のVPSは「さくらインターネットから!」

前回の記事はこちらから

VPSを使った24時間稼働システムを作成した記事はこちら

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

始めまして。このブログを運営するTomoyaです。
未経験個人開発者。AI×個人開発(Vibe Cording)で学習して参入してくれる人が増えて広がっていくと良いなと思って始めました。

実際に作成→デプロイ(公開)→運営を行ってそれについての問題や疑問を記録していきます。
また行っていく上で内容(セキュリティ・制限など)にもこだわっていきたいなと思っています。

コメント

コメントする

目次