Vercelのデプロイは成功したのに404になるときの確認手順

VercelのReady後の404をURL・出力・routing・アプリ応答に分け、Root DirectoryやSPA fallbackの確認と復旧手順を整理します。

AIものさし編集部

VercelでdeploymentがReadyなのに404なら、まず同じdeploymentのURLと問題のpathを固定します。Readyはbuildとdeployment作成の成功であり、要求したrouteが正しく応答することまでは保証しません。すぐに全pathをindex.htmlへrewriteせず、出力がないのか、routeに届かないのか、アプリが404を返したのかを分けます。

本稿はVercel上の404診断です。対象projectへのアクセス、build・deployment・DNS・設定変更は実施していません。例は架空で、読者の環境に同じ原因があるという意味ではありません。

URL・path・状態・error codeをそろえる

Team、project、deployment ID、commit、environment、URL、HTTP methodとpathを記録します。custom domainとdeployment固有のvercel.app URLを、同じpathで比べます。過去deploymentのURLと現在のdomainを比較していないかも確認します。

表は横にスクロールできます

症状最初に調べる場所避ける推測
固有URLは正常、domainだけ404domainとproject/deploymentの対応codeが必ず壊れた
両方で全routeが404build出力とframework設定DNSだけが原因
rootだけ404root routeとindexの出力全siteが未deployment
SPA内の直接アクセスだけ404client/server routingの境界全frameworkへ同じrewrite
特定のdynamic routeだけ404param・生成対象・handlerglobalなfallback追加

Vercelの404解説(新しいタブで開く)は、build後の出力とrouting metadataを分けて調べる方法を案内しています。domainだけ違う場合も、DNSを変更する前に、同じproject・同じpathを比較したか、host依存のroutingやdomain割当を確認します。

Outputで、期待する出力があるかを見る

deployment detailsのOutputとbuild logで、必要な静的ファイルやFunctionが生成されたかを確認します。ローカル開発サーバーで見えるrouteが、production buildにも含まれるとは限りません。出力がなければ、先にRoot Directory、Framework Preset、build command、Output Directoryを照合します。

monorepoなら対象appのrootとpackage/build設定を確認します。repository root、app root、生成物directoryは同じとは限りません。Next.js等のframework固有出力と、汎用静的siteのdistを取り違えないようにします。設定名を見て適当にoutやdistを指定せず、実際に生成された出力と対象frameworkの公式方式へ合わせます。

一般的な静的siteでrootだけ404なら、index.html相当の入口が出力されたかを見ます。一方、サーバー frameworkのroutingを、ファイル名だけで判断しません。生成物があるのに404なら、その時点でrouting側を調べます。

アプリへ届いた404かを確認する

Functionの呼出があるか、該当時刻・deployment・pathのruntime logを見ます。アプリのhandlerが起動して自らnot foundを返したなら、ID、検索条件、対象データ、環境差などのアプリ側診断へ進みます。handler前で止まるなら、rewrite、redirect、middleware、route定義を調べます。

logが見つからない場合、検索期間、対象environment、保持期間、filterが正しいかも確認します。静的routeにはFunctionの呼出が不要なので、logがないという理由だけで失敗にしません。機密値や個人情報を詳細logへ追加せず、requestの識別情報と状態で絞ります。

NOT_FOUNDの公式説明(新しいタブで開く)と画面のerror codeを照合します。DEPLOYMENT_NOT_FOUNDのようにdeploymentの存在やURLが関係する場合を、アプリの一件のrecordがない404と同じ修正にしないようにします。

SPA fallbackとframework routingを混ぜない

SPAの画面内遷移は成功し、同じURLのreloadだけ404なら、サーバー側がそのpathをどう解決するかを確認します。必要なfallbackは対象のSPAとdeploy方式に合わせます。APIやassetまで一括でindexへ送る設定にすると、APIがHTMLを200で返す別の障害を作る場合があります。

Next.jsなど独自のroutingを持つframeworkへ、SPA用catch-allをそのまま追加しません。既存のframework設定とvercel.json、middleware等の重複を読み、最初にどの規則が該当するかを確認します。dynamic routeでは、そのparamが静的生成の対象か、動的に処理する設計かを、そのバージョンのframework資料で確認します。

最小の差分で再確認し、結果を引き継ぐ

変更前の設定、問題URL、比較した正常route、deploymentを保存します。許可された検証環境で原因に対応する一つの差分だけを試し、必要な再buildを含む運用手順で確認します。本稿でその操作を行ったという意味ではありません。

表は横にスクロールできます

受入確認合格とする結果残る問題の例
rootと通常route期待する内容と状態rootだけ直った
直接アクセス・reload同じ画面へ到達client遷移のみ成功
API・asset本来の型と内容HTML fallbackの巻込み
存在しないroute意図した404すべて200で隠す
domain意図したdeploymentとpath別バージョンへ接続

失敗したら、今回の設定差分を戻し、別の原因候補を証拠から選び直します。domainの切替や本番deploymentは、診断とは別の運用判断です。完了記録は「Readyになった」だけでなく、どのURL・path・内容が回復し、どこを未確認にしたかまで残します。