Vercelにデプロイしたら真っ赤なエラー。ローカルでは完璧に動いているのに。
この記事では、Vercelで実際によく起きるデプロイエラーを エラーの種類別 にまとめた。エラーメッセージから原因を特定して、最短で解決できるようにしている。
デプロイ前にローカルで確認すること
Vercelにpushする前に、この3つをローカルで実行する。これだけでビルドエラーの大半を事前に防げる。
npx tsc --noEmit # TypeScriptの型チェック
npm run lint # ESLintチェック
npm run build # プロダクションビルド
npm run dev で動くことと npm run build で通ることは別物だ。dev環境ではTypeScriptエラーが警告で済むが、ビルドでは致命的エラーになる。
ありがちな見落とし:
npm run buildを一度もローカルで試さずにpushしているdevでは動くがbuildでは環境変数が足りない- TypeScriptの
strictモードがCI環境で初めて有効になる
ビルドエラーの原因と対処法
Module not found
Error: Module not found: Can't resolve './Components/Header'
原因: ファイル名の大文字小文字の不一致。macOSとWindowsはcase-insensitiveだが、Vercel(Linux)はcase-sensitiveだ。
ローカルで components/Header.tsx を作って import Header from './Components/Header' と書いても動く。Vercelでは動かない。
対処法:
# gitのcase-sensitive設定を有効にする(再発防止)
git config core.ignorecase false
import文のパスを実際のファイル名と完全に一致させる。
依存関係のエラー
npm ERR! Could not resolve dependency
原因: package-lock.json とNode.jsバージョンの不整合。ローカルではNode 22で動かしているが、Vercelのデフォルトが異なるケースがある。
対処法:
- Vercelダッシュボード → Settings → General → Node.js Version でローカルと同じバージョンを指定
package-lock.jsonを削除してnpm installし直し、再コミット
ビルドのキャッシュが壊れている
ビルドログに不可解なエラーが出て、コードを変えていないのに急に失敗する場合。
対処法: Vercelダッシュボード → Deployments → 該当デプロイの「...」メニュー → Redeploy without cache を選択。
ローカルで動くのにVercelで動かない
Vercelデプロイで最もストレスが溜まるパターン。原因はほぼ以下の3つに絞られる。
1. ファイルシステムへの書き込み
Error: EROFS: read-only file system, open '/var/task/data.json'
Serverless Functionのファイルシステムは 読み取り専用 だ。ローカルのNode.jsサーバーでは fs.writeFileSync が動くが、Vercelでは動かない。
対処法: 書き込みが必要な場合は /tmp ディレクトリを使う(上限500MB)。永続的なデータ保存にはデータベースやオブジェクトストレージを使う。
import { writeFileSync } from "fs";
import { join } from "path";
// NG: Vercelでは読み取り専用
writeFileSync("./data.json", JSON.stringify(data));
// OK: /tmpなら書き込める
writeFileSync(join("/tmp", "data.json"), JSON.stringify(data));
2. 環境変数がない
ローカルでは .env.local に書いた環境変数が使えるが、Vercelには自動で反映されない。
対処法: Vercelダッシュボード → Settings → Environment Variables に手動で追加する。.env.local をコピーするだけではだめで、Development/Preview/Production の3環境それぞれにチェックを入れること。
3. Node.jsバージョンの違い
ローカルがNode 22で、VercelがNode 20だと、ES module解決やAPI互換性で差異が出る。
対処法: Vercelダッシュボード → Settings → General → Node.js Version をローカルと一致させる。または .node-version ファイルをプロジェクトルートに置く。
ランタイムエラー(500・タイムアウト)
ビルドは成功するのに、デプロイ後にサイトが500を返す、または特定のページだけ動かないパターン。
Serverless Function has crashed
FUNCTION_INVOCATION_FAILED
主な原因:
- 未キャッチの例外(try/catchで囲まれていない処理)
- メモリ不足(Hobbyプラン: 2GB上限)
- 環境変数が未設定でDBやAPIの接続に失敗
対処法: Vercelダッシュボード → Logs でランタイムログを確認する。エラーの詳細が表示される。
FUNCTION_INVOCATION_TIMEOUT
Task timed out after 10 seconds
原因: Fluid Computeが無効の場合、Hobbyプランのデフォルトタイムアウトは 10秒 だ。現在はFluid Computeがデフォルトで有効になっており、デフォルトは300秒に延長されている。ただし古いプロジェクトや手動で無効にしている場合は10秒のままだ。
FUNCTION_PAYLOAD_TOO_LARGE
FUNCTION_PAYLOAD_TOO_LARGE
リクエストボディが 4.5MB を超えている。ファイルアップロードやJSONペイロードが大きい場合に発生する。
対処法: 大きなファイルは直接アップロードせず、署名付きURLでS3やR2に直接アップロードする設計にする。
自分のコードじゃない場合:Vercel側の障害
エラーの原因が自分のコードではないこともある。
2026年3月2日のドバイ障害 では、ドバイリージョン(dxb1)のインフラ障害が原因で 世界中のVercelユーザーのデプロイが10時間以上ブロックされた。 原因は、Vercelの仕様上 Middlewareが全リージョンにデプロイされる ため、1箇所のリージョン障害がMiddlewareを使う全プロジェクトのデプロイを止めたことだ。
コードを変えていないのにデプロイが突然失敗する場合:
- vercel-status.com を最初に確認する
- Vercel側の障害なら、復旧を待つ以外にできることはない
- 復旧後は Redeploy without cache で再デプロイする
環境変数のハマりポイント
環境変数はVercelデプロイで最も混乱しやすいテーマだ。
build-time vs runtime
Next.jsには2種類の環境変数がある。
| 種類 | プレフィックス | いつ読まれるか | 変更時 |
|---|---|---|---|
| サーバー側 | なし(DB_URL等) | リクエスト時(runtime) | 即反映 |
| クライアント側 | NEXT_PUBLIC_ | ビルド時にインライン化 | 再ビルド必須 |
よくある間違い
ダブルクォートを付けている:
# NG(Vercelダッシュボードで入力する場合)
NEXT_PUBLIC_API_URL="https://api.example.com"
# OK
NEXT_PUBLIC_API_URL=https://api.example.com
Vercelの環境変数設定ではダブルクォートは不要。付けるとクォートが値の一部になってしまう。
Preview環境にチェックを入れていない:
環境変数を追加するとき、Production/Preview/Developmentの3つのチェックボックスがある。Previewにチェックを入れないと、プレビューデプロイ(PRごとの自動デプロイ)で環境変数が読めない。
プラン別の制限を知っておく
エラーの原因がプランの制限であることも多い。
| 制限 | Hobby(無料) | Pro($20/月) |
|---|---|---|
| Function タイムアウト | 300秒(Fluid有効時) | 800秒(Fluid有効時) |
| メモリ上限 | 2 GB | 最大4 GB |
| Function サイズ | 250 MB(unzipped) | 250 MB |
| リクエストボディ | 4.5 MB | 4.5 MB |
| ビルド時間 | 45分 | 45分 |
/tmp ストレージ | 500 MB | 500 MB |
| 帯域 | 100 GB/月 | 1 TB/月 |
| Fluid Active CPU | 4時間/月 | $20クレジットで相殺 |
Hobbyプランで FUNCTION_INVOCATION_TIMEOUT が頻発するなら、10秒制限が原因の可能性が高い。Fluid Computeを有効にするか、処理を軽量化する。
まとめ
| エラー | まず確認すること |
|---|---|
| Module not found | import文の大文字小文字がファイル名と一致しているか |
| ビルド失敗 | ローカルで npm run build が通るか |
| 500エラー | Vercel Logsでランタイムエラーの詳細を確認 |
| タイムアウト | Fluid Computeの有効化、外部API呼び出しの最適化 |
| 環境変数が効かない | build-time vs runtimeの違いを確認 |
| 突然の障害 | vercel-status.com を確認 |
「ローカルで動くのにVercelで動かない」の9割は、case sensitivity・環境変数・ファイルシステムの3つだ。この3つを覚えておくだけで、デプロイエラーの大半を素早く解決できる。
Vercelの従量課金で予想外の請求が来るのを防ぐにはSpend Managementの設定ガイドも確認しておこう。