ローカルに env がない=本番に存在しない、ではなかった — Vercel×Stripe の env 別管理で詰まった話
結論
ローカル .env.local にキーが無いことと、Vercel 本番に設定されていないことは別の話です。
「本番が壊れているかも」と感じたら、推測で判断せず最初にこの 2 コマンドを叩いてください。
# 本番に設定されている env を一覧する
vercel env ls production
# 決済が通るか直接 LIVE モードで確認する
# → Stripe Dashboard → Products → Price ID を本番で確認
これで壊れていないことが確認できたら、「本番は正常。0 件はまだ誰も完了していないだけ」という解釈が正しい可能性が高いです。
この記事の前提
筆者が運営している masatoman.net のサブスクリプション決済(Next.js + Vercel + Stripe)で発生した検証ミスの実録です。
スタック:
- Next.js App Router(Vercel デプロイ)
- Stripe サブスクリプション決済
- Supabase(購読完了レコードの保存先)
発生: 2026-06-17、Stripe 決済導線の動作確認フェーズ中。
読者のよくある詰まり
「ローカルで試したらエラーが出た(または env が無い)。本番も同じはずだ」
このパターンで不必要なデバッグ時間を消費した経験がある方は多いはずです。
ローカルと Vercel 本番は環境変数を完全に別々に管理する設計になっています。.env.local に書いたものが Vercel に自動的に反映されることはありません。
| 場所 | 環境変数の管理 |
|---|---|
| ローカル開発 | .env.local(gitignore 対象) |
| Vercel production | Dashboard → Settings → Environment Variables |
| Vercel preview | 同上(production と別設定可能) |
この構造を意識せずに開発していると、「ローカルに無い = 本番も無い」という誤った推測が生まれます。
実際に起きたこと
状況
2026-06-17、サブスクリプション決済の導線検証中。Supabase の completions テーブルのレコードが 0 件だった。
ローカルの .env.local を確認すると、STRIPE_PRICE_ID の記載がなかった。
出した結論(誤り)
「ローカル env に price ID がない + 完了件数 0 件 → 本番 Vercel にも price ID が設定されていない → Stripe 決済が壊れている」
実際の状態
vercel env ls production を叩いたところ、STRIPE_PRICE_ID は本番に設定済みだった。
Stripe の LIVE モードで決済画面を直接開くと、チェックアウトページまで正常に到達できた。
推測は完全に外れていた。
2026-06-17、Stripe 決済導線の確認中に「本番が壊れている」と判断してデバッグを始めたが、実際は本番 Vercel に price ID は設定済みで決済画面は正常動作していた。ローカル env の欠落と本番の壊れを混同した検証ミスだった。
原因分析
ミスの構造
今回の誤判断は 2 つの間違いを組み合わせたものでした。
間違い 1: ローカル env の欠落を本番の欠落と混同
.env.local はローカル開発専用のファイルです。本番 Vercel の env とは完全に独立しています。ローカルに無くても本番にある、本番にあってもローカルに無い、という状態は普通に起きます。
間違い 2: 完了 0 件を「壊れている証拠」として扱った
完了件数が 0 件だった原因には複数の解釈があります:
- 本番が壊れていてチェックアウトが通らない(今回の誤判断)
- 本番は正常だが、まだ誰も完了していない(実際の状態)
- 完了は発生しているが記録に失敗している(Supabase の問題)
この 3 つを区別せずに最初の解釈を採用したのがミスでした。
なぜこのミスが起きやすいか
個人開発では「ローカルで確認 → 本番にデプロイ → ローカルで動作確認」のサイクルが多くなります。本番を直接確認する習慣が薄くなりやすい。
加えて、env 管理は設定する本人しか把握しておらず、「設定したかどうか」の記憶が曖昧になりがちです。
判断基準: 本番が壊れているかを確かめる前に
「本番が壊れているかも」と感じた時、推測で動く前に以下の順序で確認してください。
Step 1: 本番 env を直接確認する
vercel env ls production
使っているキー名が production 欄に存在するか確認します。
Step 2: 本番フローを直接開いてみる
Stripe であれば Stripe Dashboard の LIVE モード、または本番 URL を実際に開いて決済画面まで到達できるか確認します。
ローカルの状態を本番の代理にしない。本番は本番で直接確認する。
Step 3: 0 件の解釈を複数持つ
完了件数や登録件数が 0 件のとき、即座に「壊れている」と判断しない。「まだ誰も完了していない」「まだ誰も試していない」という解釈も同時に持ちます。
壊れている証拠と、単に使われていない証拠は別物です。
今日やること(3 つ以内)
vercel env ls productionを一度叩いて現状を把握する — 本番に何が設定されていて何が無いかを確認しておく- Stripe を使っているなら LIVE モードの決済画面を実際に開く — チェックアウトページまで到達できるか、今すぐ自分で確かめる
- 「完了 0 件」の原因仮説を最低 2 つ書き出す習慣をつける — 即座に「壊れている」と結論せず、代替仮説を一つ挟むクセをつける