pnpm-lock.yaml Basi yang Bikin Deploy Vercel Gagal
Vercel nebak package manager dari lockfile, bukan package.json. pnpm-lock.yaml basi dari eksperimen lama bikin deploy gagal pakai ERR_PNPM_OUTDATED_LOCKFILE.
Deploy beres di lokal, terus Vercel nolak. Pesan errornya satu baris doang di log build: ERR_PNPM_OUTDATED_LOCKFILE, pnpm-lock.yaml nggak sinkron sama package.json. Padahal saya jarang banget nyentuh pnpm di project ini. Tapi begitu buka root folder frontend, filenya ada: pnpm-lock.yaml, 9.285 baris, terakhir di-generate 12 Agustus.
Dua minggu sebelum kejadian, saya nambahin empat dependency baru buat fitur embed blog: echarts, mermaid, recharts, dan @teispace/next-themes. Empat-empatnya masuk lewat npm install, tercatat rapi di package.json dan package-lock.json. pnpm-lock.yaml nggak ikut di-update, karena memang nggak ada pnpm yang jalan. File itu tinggal numpang lewat dari zaman awal project.
Vercel nggak baca package.json dulu
Dugaan pertama saya sempat nyasar ke cache build. Toh dependency-nya udah kepasang, package-lock.json juga fresh. Tapi cara kerja Vercel emang bukan gitu: pas deploy, dia nyari lockfile di project, terus dari situ menebak package manager yang dipakai. Dokumentasinya jelas bilang begitu: inferring dari lock file, bukan dari package.json. Kebetulan pnpm-lock.yaml duluan ketemu, dia pun mutusin project ini project pnpm dan jalanin pnpm install.
Ada satu pengecualian: kalo project pakai Corepack dan package.json punya field packageManager, Vercel pakai itu. Punya saya kosong, jadi deteksi lockfile yang menang. Selengkapnya ada di docs package managers Vercel.
Yang bikin lama nggak ketahuan: lokal nggak pernah kena. npm install di laptop saya nggak ngecek pnpm-lock.yaml sama sekali, jadi semua keliatan sehat. Baru pas CI Vercel nyobain jalanin pnpm dengan lockfile basi itu, tabrakannya kelihatan. Makanya file sisa eksperimen kayak gini bahaya dia diam-diam — lokal hijau, deploy merah, dan jarak antara keduanya dua minggu.
Trus kenapa install-nya langsung gagal, bukan cuma warning? Karena pnpm di CI jalan dengan flag frozen-lockfile secara default. Aturan itu tercatat di docs pnpm install. Artinya lockfile nggak boleh diutak-atik sama sekali; kalo ternyata nggak sinkron sama package.json, install berhenti. Versi pnpm sendiri juga ikut nebak dari lockfileVersion di dalam file. Saya nggak pernah nge-set itu, dan nomor versi pnpm yang diambil Vercel dari file lama ini bisa beda dari yang saya pakai lokal. Ini pola kejadian yang udah lama dikenal: issue vercel/vercel#8272 dari 2022 sampai thread komunitas ERR_PNPM_OUTDATED_LOCKFILE akhir 2025 isinya kasus yang sama persis.
Fix paling pendek: hapus file yang bohong
Urutan opsi yang saya pikirin:
- Regenerate pnpm-lock.yaml pakai pnpm biar sinkron. Ini fix kalo emang mau pnpm. Tapi berarti ikut nge-maintain dua lockfile buat satu project. Buat monorepo besar yang emang pnpm-first, mungkin masuk akal. Buat saya, enggak.
- Nyalain Corepack dan isi field packageManager. Ini jalan resmi buat "pin" npm, tapi nambah satu konfigurasi lagi yang harus dijaga, dan tetap ninggalin file bohong itu di repo.
- Hapus pnpm-lock.yaml. Toolchain project ini dari awal npm — Dockerfile jalanin
npm ci, package-lock.json selalu ikut ter-update tiap install. Satu file itu doang yang beda cerita.
Saya ambil yang ketiga. Satu commit di 27 Agustus: minus 9.285 baris, deploy beres. Fix paling pendek yang bisa saya bayangkan buat masalah begini: file yang nunjukin package manager yang salah tinggal dihapus. Kalo suatu saat project ini emang pindah ke pnpm, lockfile-nya bakal di-generate ulang dari nol — bukan numpang pakai file lama yang udah basi dua minggu.
Di situasi kebalikannya, script-nya cuma dibalik. Project npm yang punya yarn.lock atau bun.lockb sisa eksperimen lama bakal kena masalah yang sama, karena deteksi Vercel sama buat semua package manager. Dan kalo suatu saat pnpm emang jadi pilihan, langkahnya cuma: regenerate lockfile lokal sampai bener-bener sinkron, baru push. Jangan pernah tinggalin lockfile basi di repo yang di-deploy tiap hari.
Yang saya bawa dari kejadian ini: satu project, satu lockfile, dan yang jadi patokan buat deploy itu file yang sama dengan yang kita rawat lokal. Kedengeran klise, tapi kejadian hari itu buktiin kalo nggak. Buat yang mau lihat kerusakan versi lain dari mesin deploy yang sama, saya sempat nulis soal revert sitemap yang bentrok sama route Next 16.