未追跡のpnpm-lock.yamlがVercelをpnpmプロジェクトと誤検知させた
※本記事にはアフィリエイトリンクを含む場合があります。内容は広告の有無に影響されません。
結論
`.vercelignore` が存在すると Vercel CLI は `.gitignore` を参照しなくなるため、未追跡のまま残っていた `pnpm-lock.yaml` もアップロード対象に含まれ、Vercel はプロジェクトを pnpm と判定する。
結論
正本は npm(package-lock.json)のリポジトリなのに、gitに一度もコミットしていない pnpm-lock.yaml が残っていたせいで、Vercel がプロジェクトを pnpm と誤判定してビルドが型エラーで落ちました。 .vercelignore が存在すると Vercel CLI は .gitignore を見なくなるため、コミットしていないファイルでも .vercelignore に書いていない限りそのままアップロードされます。
症状
このリポジトリの依存管理は npm で、package.json の stripe は ^22.3.1 を指定しています。
"stripe": "^22.3.1",
npm はこれを 22.3.1 に固定して package-lock.json に書き込んでいます。
"node_modules/stripe": {
"version": "22.3.1",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-22.3.1.tgz",
ところが作業ディレクトリには pnpm-lock.yaml と pnpm-workspace.yaml も置かれたままで、こちらは一度も git add されていない未追跡ファイルでした。ビルドを Vercel に投げると、stripe の型定義が食い違って型エラーで落ちます。
原因
.vercelignore には元々、こう書かれていました。
.env*
/scripts
/supabase
/test-results
/README.md
pnpm-lock.yaml はここに入っていません。.vercelignore ファイルが存在する場合、Vercel CLI はアップロード対象の除外を .vercelignore の記述だけで決め、.gitignore は参照しません。 そのため「git に上げていないから大丈夫」という判断が通用せず、未追跡のまま作業ディレクトリに残っていた pnpm-lock.yaml / pnpm-workspace.yaml がそのままアップロードされていました。
Vercel のビルド環境は、アップロードされたファイルの中に pnpm-lock.yaml があることを根拠にプロジェクトを pnpm と判定します。判定が pnpm に倒れると、依存解決も pnpm のロックファイルに従います。pnpm-lock.yaml 側では stripe が
stripe@22.6.0:
に解決されていて、npm 側が固定していた 22.3.1 とは異なるバージョンでした。この差分がそのまま型エラーとしてビルドを落としていました。
直す
.vercelignore に2行を追加し、pnpm-lock.yaml と pnpm-workspace.yaml を明示的にアップロード対象から外しました。
/pnpm-lock.yaml
/pnpm-workspace.yaml
ローカルのファイル自体は削除していません。Vercel に上がらなくなっただけで、.vercelignore が「アップロードするかどうか」を決める唯一の場所であることに変わりはなく、除外したい未追跡ファイルは今後もここに書く必要があります。
再発防止
この記事の根拠には、pnpm ロックの混入を機械的に検知する仕組みを追加したという記述はありません。今回の直し方も、見つかった2ファイルを .vercelignore に足しただけです。
構造として見えるのは、「git に上げていない」と「Vercel にも上がらない」は別の話だということです。.vercelignore を一度でも作った時点で、除外の基準は .gitignore ではなく .vercelignore の記述内容そのものに切り替わります。未追跡のファイルが手元に残っているだけなら実害はありませんが、.vercelignore があるリポジトリでは、そのファイルが正本のパッケージマネージャと衝突する種類のものかどうかを、置かれた時点で確認する必要があります。
よくある質問
Q1.vercelignoreがあると何が変わるのですか?
Vercel CLIは、.vercelignoreファイルが存在する場合はそちらだけを参照し、.gitignoreは見なくなります。今回の.vercelignoreには元々pnpm-lock.yaml / pnpm-workspace.yamlの除外が入っていなかったため、gitに一度もコミットしていない未追跡のファイルでも、そのままアップロード対象に含まれました。
Q2npmとpnpmで依存解決がどう食い違ったのですか?
package.jsonのstripeの指定は^22.3.1で、npm側のpackage-lock.jsonはそのまま22.3.1に解決していました。一方、ローカルに残っていたpnpm-lock.yamlは22.6.0に解決していて、Vercelがpnpmと判定してこちらを使ったため、型定義の食い違いでビルドが型エラーになりました。
Q3直し方はpnpm-lock.yamlを削除することですか?
削除はしていません。.vercelignoreにpnpm-lock.yamlとpnpm-workspace.yamlを明示的に追加し、Vercelへのアップロード対象から外すことで直しています。ローカルのファイル自体はそのまま残っています。
確認した環境
- package.json の stripe 指定は ^22.3.1(npm解決 22.3.1 / pnpm解決 22.6.0)
- 2026-09-16 にkimiteras-portalのデプロイ前レビューで発見・修正
この記事の根拠
- ファイル 1〜14行目コミット 3e95468
- JSONファイル 26〜26行目コミット 62a03f7
- JSONファイル 7979〜7981行目コミット 62a03f7
本文の主張は、上の記録に書かれていることだけです。運用しているリポジトリは非公開のため リンクは張れませんが、どのファイルの何行目を、どのコミット時点で見て書いたかは 記事ごとに残しています。推測で書いた箇所はありません。