Error Cannot find module 'ajv/dist/compile/codegen' adalah salah satu error yang cukup menjengkelkan dalam ekosistem React dan Node.js. Error ini sering muncul secara tiba-tiba—terutama setelah proses instalasi dependensi atau pembaruan paket—dan membuat aplikasi yang sebelumnya berjalan normal menjadi tidak bisa dijalankan sama sekali. Dalam artikel ini, kita akan membahas tuntas apa yang sebenarnya terjadi, akar masalahnya, cara memperbaikinya secara permanen, hingga langkah pencegahan agar error ini tidak kembali muncul di masa depan.
Apa yang Sebenarnya Dikeluhkan Error Ini
Ketika error ini muncul, yang kamu lihat di terminal biasanya adalah pesan seperti berikut:
Error: Cannot find module 'ajv/dist/compile/codegen'
Require stack:
- /path/to/project/node_modules/ajv-keywords/dist/definitions/limit.js
- /path/to/project/node_modules/ajv-keywords/dist/index.js
- /path/to/project/node_modules/schema-utils/dist/validate.js
- ...Atau variasi yang lebih singkat:
Module not found: Error: Can't resolve 'ajv/dist/compile/codegen' in '/path/to/project/node_modules/ajv-keywords/dist/definitions'Pesan error ini, meskipun terlihat teknis, sesungguhnya memiliki arti yang cukup sederhana. Dalam bahasa Indonesia: sistem tidak bisa menemukan modul ajv/dist/compile/codegen yang dibutuhkan oleh paket lain (biasanya ajv-keywords) untuk bisa berjalan. Ini adalah error resolusi modul—Node.js atau bundler (seperti webpack) mencoba memuat sebuah file dari paket ajv, tetapi file tersebut tidak ada di lokasi yang diharapkan.
Paket ajv sendiri adalah Another JSON Validator, sebuah library validasi JSON schema yang sangat cepat dan banyak digunakan di ekosistem JavaScript. Paket ajv-keywords adalah paket tambahan yang menyediakan custom keywords untuk AJV, dan paket ini mengimpor file dari path ajv/dist/compile/codegen secara langsung. Ketika struktur folder ajv berubah antar versi—misalnya file codegen dipindahkan, di-rename, atau dihapus—maka impor yang dilakukan oleh ajv-keywords menjadi rusak dan error inilah yang muncul.
Kenapa error ini sering muncul secara tiba-tiba? Jawabannya ada di mekanisme resolusi dependensi npm dan yarn. Ketika kamu menjalankan npm install atau yarn install, package manager menyelesaikan pohon dependensi dan bisa saja memasang versi ajv yang tidak kompatibel dengan versi ajv-keywords yang juga terpasang. Ini terutama terjadi ketika ada paket-paket berbeda dalam pohon dependensi yang masing-masing membutuhkan versi ajv yang berbeda, dan npm menyelesaikannya dengan memasang dua versi ajv secara bersamaan—atau justru menimpa satu dengan yang lain.
Perhatikan contoh skenario berikut. Kamu memiliki package.json seperti ini:
{
"dependencies": {
"react": "^18.2.0",
"webpack": "^5.75.0",
"schema-utils": "^3.3.0"
}
}Ketika kamu menjalankan:
npm installNpm akan memasang schema-utils, yang bergantung pada ajv-keywords, yang pada gilirannya bergantung pada ajv. Jika ada paket lain (misalnya webpack atau dependensi dari webpack) yang juga bergantung pada ajv tetapi versi yang berbeda, resolusi bisa berujung pada ketidakcocokan. File codegen.js yang diharapkan ada di ajv/dist/compile/ ternyata tidak ada karena versi ajv yang terpasang memiliki struktur folder yang berbeda.
Error ini juga bisa muncul setelah kamu menghapus node_modules dan menginstal ulang, setelah berpindah branch di git, setelah upgrade Node.js, atau setelah menambahkan paket baru yang secara transitif membawa versi ajv yang tidak kompatibel. Intinya, setiap kali pohon dependensi direkonstruksi, ada potensi versi ajv yang terpasang tidak sesuai dengan ekspektasi ajv-keywords, dan error inilah konsekuensinya.
Akar Masalah yang Paling Sering
Setelah menangani error ini berkali-kali di berbagai proyek, berikut adalah root cause yang paling sering menjadi penyebab, diurutkan dari yang paling umum:
1. Versi ajv dan ajv-keywords yang tidak kompatibel. Ini adalah penyebab nomor satu. Paket ajv-keywords@3.x dirancang untuk bekerja dengan ajv@6.x, sementara ajv-keywords@5.x dirancang untuk ajv@8.x. Ketika ajv-keywords versi 3 terpasang tetapi ajv yang terpasang adalah versi 8 (atau sebaliknya), struktur folder berbeda secara drastis. Versi 6 ajv menyimpan file codegen di path yang berbeda dengan versi 8. Import path ajv/dist/compile/codegen hanya valid di ajv versi 8, jadi jika versi 6 yang terpasang, file tersebut memang tidak ada.
2. Duplicate versi ajv di node_modules. Karena npm secara default melakukan hoisting (menaikkan paket ke akar node_modules), dua paket yang membutuhkan versi ajv berbeda bisa berkonflik. Misalnya, schema-utils@3 membutuhkan ajv@6, tetapi paket lain di pohon dependensi membutuhkan ajv@8. npm mungkin hanya memasang satu versi di root node_modules, dan versi yang kalah tidak bisa menemukan file yang dibutuhkan.
3. Cache npm atau yarn yang korup. Terkadang, cache package manager menyimpan snapshot versi yang sudah outdated atau korup. Ketika instalasi dilakukan, npm mengambil dari cache yang tidak merepresentasikan kondisi terbaru dari registry, menghasilkan pohon dependensi yang inkonsisten.
4. File package-lock.json atau yarn.lock yang tidak sinkron. Lock file yang sudah outdated—misalnya sudah di-commit ke git beberapa minggu lalu dan tidak diperbarui setelah perubahan dependensi—bisa menyebabkan resolusi yang berbeda saat npm install dijalankan di mesin yang berbeda atau setelah cache dibersihkan.
5. Penggunaan npm ci dengan lock file yang konflik. Perintah npm ci sangat ketat dan akan gagal jika ada inkonsistensi antara package.json dan package-lock.json. Namun dalam beberapa kasus, perintah ini justru memasang kombinasi yang memicu error ini karena paksa mengikuti lock file yang sudah tidak kompatibel.
Cara memastikan penyebab mana yang kamu alami:
- Jalankan
npm ls ajv(atauyarn why ajv) untuk melihat semua versiajvyang terpasang dan siapa yang membutuhkannya. Jika ada lebih dari satu versi, penyebabnya adalah duplikasi versi (root cause #1 atau #2). - Periksa apakah file
ajv/dist/compile/codegen.jsada:ls node_modules/ajv/dist/compile/. Jika foldercompiletidak ada atau kosong, kemungkinan versiajvyang terpasang adalah versi 6 (root cause #1). - Bersihkan cache dan instal ulang. Jika error hilang, penyebabnya adalah cache korup (root cause #3).
- Bandingkan hash di
package-lock.jsondengan yang di registry. Jika tidak cocok, lock file mungkin korup (root cause #4).
Cara Memperbaiki
Bagian ini membahas langkah-langkah perbaikan secara berurutan, dari yang paling cepat hingga yang paling menyeluruh. Ikuti langkah-langkah ini satu per satu sampai error teratasi.
Langkah 1: Hapus dan Instal Ulang Dependensi
Langkah paling sederhana yang sering kali langsung berhasil:
rm -rf node_modules
rm package-lock.json
npm installAtau jika menggunakan yarn:
rm -rf node_modules
rm yarn.lock
yarn installOutput yang diharapkan: Proses instalasi selesai tanpa error, dan ketika kamu menjalankan npm start atau yarn start, aplikasi berjalan normal tanpa pesan Cannot find module.
Namun, jika langkah ini tidak berhasil, lanjut ke langkah berikutnya.
Langkah 2: Bersihkan Cache Package Manager
Cache yang korup bisa menyebabkan versi yang salah terpasang:
npm cache clean --force
rm -rf node_modules
rm package-lock.json
npm installUntuk yarn:
yarn cache clean
rm -rf node_modules
rm yarn.lock
yarn installOutput yang diharapkan: Setelah instalasi ulang, jalankan npm ls ajv dan pastikan hanya ada satu versi ajv yang terpasang (idealnya versi 8.x).
Langkah 3: Pasang Versi ajv dan ajv-keywords yang Kompatibel Secara Eksplisit
Jika duplikasi versi adalah masalahnya, pasang versi yang kompatibel secara eksplisit di package.json:
npm install ajv@8 ajv-keywords@5 --saveAtau, jika paket-paketmu masih membutuhkan ajv@6:
npm install ajv@6 ajv-keywords@3 --savePerintah ini memastikan versi yang tepat terpasang di root node_modules dan menjadi resolusi tunggal untuk seluruh pohon dependensi.
Output yang diharapkan: package.json sekarang memuat entri eksplisit untuk ajv dan ajv-keywords, dan npm ls ajv menunjukkan hanya satu versi.
Langkah 4: Gunakan overrides (npm) atau resolutions (yarn)
Jika ada paket transitif yang memaksa versi ajv tertentu, kamu bisa meng-override-nya:
Untuk npm (versi 8+), tambahkan di package.json:
{
"overrides": {
"ajv": "8.12.0",
"ajv-keywords": "5.1.0"
}
}Untuk yarn, tambahkan:
{
"resolutions": {
"ajv": "8.12.0",
"ajv-keywords": "5.1.0"
}
}Kemudian jalankan ulang instalasi:
rm -rf node_modules
npm installOutput yang diharapkan: Semua dependensi yang membutuhkan ajv akan menggunakan versi 8.12.0, menghilangkan duplikasi dan inkonsistensi.
Langkah 5: Perbaiki dengan npm dedupe
Kadang-kadang, npm memasang versi yang sama di beberapa lokasi dalam node_modules. Deduplication bisa membantu:
npm dedupeOutput yang diharapkan: npm merestrukturisasi node_modules sehingga paket-paket duplikat dijadikan satu.
Verifikasi Solusi Berhasil
Setelah menjalankan langkah perbaikan, verifikasi dengan urutan berikut:
# 1. Pastikan file yang dicari ada
ls node_modules/ajv/dist/compile/codegen.js
# 2. Pastikan hanya satu versi ajv
npm ls ajv
# 3. Jalankan aplikasi
npm startJika file codegen.js ada, hanya ada satu versi ajv, dan aplikasi berjalan tanpa error, maka masalah sudah teratasi secara permanen.
Mencegah Error Ini Kembali
Memperbaiki error saja tidak cukup jika tidak ada langkah pencegahan. Berikut strategi dan konfigurasi yang bisa mencegah error ini muncul kembali.
1. Selalu Commit Lock File
Lock file (package-lock.json, yarn.lock, atau pnpm-lock.yaml) adalah jaminan bahwa setiap orang dalam tim dan setiap environment (CI/CD, staging, production) mendapatkan versi dependensi yang persis sama. Jangan pernah menambahkannya ke .gitignore. Dengan lock file yang konsisten, resolusi dependensi menjadi deterministik dan kemungkinan inkonsistensi versi ajv berkurang drastis.
# Pastikan lock file di-commit
git add package-lock.json
git commit -m "chore: update lock file"2. Gunakan overrides atau resolutions Secara Proaktif
Bahkan jika error belum muncul, menambahkan override untuk paket yang diketahui bermasalah adalah praktik defensif yang baik:
{
"overrides": {
"ajv": "^8.12.0",
"ajv-keywords": "^5.1.0"
}
}Konfigurasi ini memaksa seluruh pohon dependensi menggunakan versi yang kompatibel, terlepas dari apa yang dideklarasikan oleh paket transitif.
3. Gunakan npm ci di CI/CD, Bukan npm install
Perintah npm ci menginstal dependensi strictly berdasarkan lock file tanpa memodifikasinya. Ini lebih deterministik dan menghindari "drift" versi:
# Contoh GitHub Actions
- name: Install dependencies
run: npm ci4. Best Practice: Audit Dependensi Secara Berkala
Jalankan npm audit secara berkala dan perbarui paket yang memiliki vulnerability atau inkonsistensi:
npm audit fixAtau gunakan tools seperti npm-check-updates untuk memperbarui dependensi secara terkontrol:
npx npm-check-updates -u
npm install5. Perbedaan Antar OS
Perlu diperhatikan bahwa ada nuansa perbedaan antar sistem operasi yang bisa mempengaruhi munculnya error ini:
- Windows: Path di Windows menggunakan backslash (
\), dan terkadang symlink dinode_modulestidak bekerja dengan baik, terutama jika proyek berada di drive yang berbeda. Jika kamu mengalami error ini di Windows tetapi tidak di macOS/Linux, coba aktifkan Developer Mode di Windows 10/11 untuk mengizinkan symlink, atau gunakannpm install --no-optionaluntuk menghindari paket optional yang mungkin membawa versiajvberbeda.
# Di Windows, pastikan symlink diizinkan
npm config set ignore-scripts false
npm installmacOS/Linux: Case-sensitive filesystem di Linux bisa menyebabkan masalah jika ada paket yang mengimpor dengan case yang berbeda (misalnya
Ajvvsajv). Meskipun ini jarang terkait error spesifik ini, pastikan nama path persis sesuai.WSL (Windows Subsystem for Linux): Performa filesystem di WSL, terutama jika
node_modulesberada di drive Windows (/mnt/c/), bisa sangat lambat dan terkadang menyebabkan instalasi korup. Solusi terbaik: simpan proyek di filesystem native WSL (~/projects/).
# Di WSL, pindahkan proyek ke filesystem native
cp -r /mnt/c/Users/nama/project ~/project
cd ~/project
npm install6. Konfigurasi .npmrc untuk Stabilitas
Buat file .npmrc di root proyek dengan konfigurasi berikut untuk meningkatkan stabilitas resolusi dependensi:
# .npmrc
save-exact=true
package-lock=true
legacy-peer-deps=falseOpsi save-exact=true memastikan versi yang dipasang dicatat secara eksak (tanpa caret ^ atau tilde ~) di package.json, mengurangi potensi versi bergeser saat instalasi ulang.
Diagnosis Lebih Dalam
Jika semua solusi di atas sudah dicoba tetapi error masih persisten, saatnya melakukan diagnosis yang lebih mendalam.
1. Periksa Struktur node_modules Secara Manual
Kadang-kadang, hoisting yang dilakukan npm menyembunyikan masalah. Periksa apakah ada versi ajv yang bersarang di dalam subdirektori paket lain:
find node_modules -name "ajv" -type dOutput yang mungkin:
node_modules/ajv
node_modules/schema-utils/node_modules/ajv
node_modules/webpack/node_modules/ajvJika ada lebih dari satu direktori ajv, berarti ada duplikasi. Paket yang mengimpor ajv/dist/compile/codegen mungkin merujuk ke versi yang salah. Solusi: gunakan overrides atau resolutions seperti yang dibahas di langkah 4, atau pertimbangkan beralih ke pnpm yang mengelola dependensi secara lebih ketat dengan struktur content-addressable store.
2. Baca Log Instalasi dengan Verbose
Jalankan instalasi dengan flag verbose untuk melihat resolusi dependensi secara detail:
npm install --loglevel verboseAtau untuk informasi yang lebih mendalam:
npm install --loglevel silly 2>&1 | tee install-log.txtCari baris yang menyebutkan ajv dalam log tersebut. Perhatikan versi mana yang direlokasikan (hoisted) dan mana yang ditempatkan di subdirektori. Log ini juga akan menunjukkan jika ada warning tentang peer dependency yang unmet—yang sering kali adalah petunjuk awal inkonsistensi versi.
3. Gunakan npm explain untuk Menguji Paket Bermasalah
Jika ajv-keywords yang bermasalah, jalankan:
npm explain ajv-keywordsPerintah ini akan menunjukkan mengapa versi tertentu dari ajv-keywords terpasang, paket mana yang memintanya, dan apakah ada conflict.
4. Periksa Apakah Ada Post-Install Script yang Korup
Beberapa paket menjalankan script postinstall yang bisa memodifikasi node_modules:
npm ls --long | grep postinstallJika ada paket dengan postinstall script yang mencurigakan, coba instal tanpa menjalankan script:
npm install --ignore-scriptsKemudian jalankan script secara manual satu per satu untuk mengidentifikasi mana yang menyebabkan masalah.
5. Beralih ke Package Manager yang Lebih Ketat
Pnpm secara default menggunakan struktur symlink yang ketat di mana setiap paket hanya bisa mengakses dependensi yang eksplisit dideklarasikan. Ini mengeliminasi hampir seluruh masalah hoisting dan duplikasi:
# Instal pnpm
npm install -g pnpm
# Hapus node_modules dan lock file lama
rm -rf node_modules package-lock.json
# Instal dengan pnpm
pnpm installPnpm juga memiliki mekanisme pnpm.overrides di package.json yang bekerja mirip dengan resolutions di yarn:
{
"pnpm": {
"overrides": {
"ajv": "8.12.0"
}
}
}6. Sumber Resmi untuk Deep-Dive
Untuk pemahaman yang lebih mendalam tentang mekanisme resolusi modul dan masalah dependensi di ekosistem npm, berikut adalah sumber-sumber resmi yang direkomendasikan:
- Dokumentasi npm tentang resolusi dependensi: docs.npmjs.com/cli/v9/commands/npm-install — membahas algoritma resolusi, hoisting, dan penanganan duplikasi.
- Repository GitHub
ajv: github.com/ajv-validator/ajv — changelog dan issue tracker berisi diskusi tentang breaking changes antar versi dan kompatibilitas denganajv-keywords. - Repository GitHub
ajv-keywords: github.com/ajv-validator/ajv-keywords — README secara eksplisit menyebutkan versiajvyang kompatibel untuk setiap versiajv-keywords. - RFC npm overrides: github.com/npm/rfcs/blob/main/implemented/0019-maps-vs-overrides.md — menjelaskan mekanisme overrides secara teknis.
- Dokumentasi pnpm tentang peer dependencies: pnpm.io/how-peers-are-resolved — membahas mengapa pnpm lebih ketat dan bagaimana ini mencegah masalah inkonsistensi versi.
Sebagai catatan penutup, error Cannot find module 'ajv/dist/compile/codegen' pada dasarnya adalah gejala dari masalah yang lebih luas dalam manajemen dependensi JavaScript: ketidaksinkronan versi di pohon dependensi. Memahami mekanisme resolusi dependensi dan mengadopsi praktik pengelolaan dependensi yang disiplin—lock file yang konsisten, override yang proaktif, dan package manager yang ketat—bukan hanya akan memperbaiki error ini, tetapi juga mencegah kelas error serupa di masa depan. Dengan langkah-langkah yang telah dibahas di atas, kamu seharusnya kini memiliki pemahaman yang utuh tentang masalah ini dan peralatan yang cukup untuk mengatasinya secara permanen.