Node.js adalah runtime yang sangat populer di kalangan developer JavaScript, tapi tak urung dari berbagai error yang kerap muncul baik saat development maupun production. Error-error ini seringkali membingungkan karena pesan yang ditampilkan terkesan teknis dan sulit diuraikan, terutama bagi developer yang baru bermigrasi dari bahasa pemrograman lain. Artikel ini akan mengupas tuntas pesan-pesan error paling umum di Node.js, apa artinya, kenapa muncul, dan bagaimana cara memperbaikinya secara permanen.
Pesan Error & Artinya
Ketika Node.js mengalami kegagalan, ia akan melempar (throw) sebuah error dengan pesan tertentu ke stderr. Berikut adalah beberapa kutipan pesan error asli yang paling sering ditemui:
1. Module Not Found
Error: Cannot find module 'express'
Pesan ini muncul ketika Node.js tidak dapat menemukan modul yang kamu require() atau import. Arti singkatnya: paket atau file yang kamu referensikan tidak ada di lokasi yang dicari oleh Node. Ini adalah error paling klasik dan hampir setiap developer Node.js pernah mengalaminya setidaknya sekali.
2. Port Sudah Dipakai (EADDRINUSE)
Error: listen EADDRINUSE: address already in use :::3000
Pesan ini berarti aplikasi mencoba mendengarkan (listen) di port 3000, tapi port tersebut sudah ditempati oleh proses lain. Dalam bahasa Indonesia sederhana: "Port yang kamu pakai sudah dipakai program lain, jadi aplikasimu nggak bisa start."
3. File Tidak Ditemukan (ENOENT)
Error: ENOENT: no such file or directory, open './config.json'
ENOENT adalah singkatan dari "Error NO ENTry", yang dalam konteks filesystem berarti file atau direktori yang ingin diakses tidak ada. Node.js gagal membuka config.json karena file tersebut memang tidak berada di path yang ditentukan.
4. Unhandled Promise Rejection
UnhandledPromiseRejectionWarning: TypeError: Cannot read properties of undefined (reading 'name')
Error ini muncul ketika sebuah Promise di-reject tapi tidak ada handler .catch() atau try/catch yang menangani penolakan tersebut. Di dalamnya terdapat TypeError yang menandakan kamu mencoba mengakses properti name dari nilai undefined—sesuatu yang tidak mungkin dilakukan di JavaScript.
5. SyntaxError: Unexpected token
SyntaxError: Unexpected token 'import'
Pesan ini muncul ketika Node.js menemukan sintaks yang tidak dipahami di versi yang sedang digunakan. Contoh klasik: menggunakan import ES Module padahal Node.js menjalankan file sebagai CommonJS (require).
Kenapa error-error ini muncul? Intinya, Node.js sangat ketat soal resolusi modul, manajemen port, akses filesystem, dan penanganan asynchronous. Setiap pelanggaran aturan di salah satu area tersebut akan langsung dilempar sebagai error tanpa toleransi.
Kenapa Ini Terjadi
Berikut adalah root cause dari error-error di atas, diurutkan dari yang paling sering terjadi:
Modul belum di-install atau salah install path — Ini adalah penyebab paling dominan dari
Cannot find module. Kamu mungkin lupa menjalankannpm installsetelah clone repository, atau paket ter-install dinode_modulesproyek lain karena salah direktori. Cara memastikan: jalankanls node_modules | grep <nama-paket>dan periksa apakah folder paket tersebut ada.Proses sebelumnya masih berjalan di port yang sama — Penyebab paling umum dari
EADDRINUSE. Sering terjadi ketika kamu menghentikan server denganCtrl+Ctapi proses zombie masih nyangkut, atau kamu menjalankan dua instance aplikasi sekaligus. Cara memastikan: jalankanlsof -i :<port>di Linux/macOS ataunetstat -ano | findstr :<port>di Windows untuk melihat PID proses yang memonopoli port tersebut.Path file salah atau working directory berbeda — Penyebab utama
ENOENT. Relative path di Node.js di-resolve berdasarkan current working directory (CWD), bukan lokasi file script. Jika kamu menjalankannode src/app.jsdari direktori yang berbeda, path./config.jsonakan merujuk ke CWD, bukan foldersrc/. Cara memastikan: tambahkanconsole.log(process.cwd())dan bandingkan dengan__dirnameuntuk melihat apakah keduanya sesuai harapan.Versi Node.js tidak mendukung sintaks yang digunakan — Penyebab
SyntaxError: Unexpected token. Misalnya,import/exportES Module baru didukung penuh di Node.js v14+ dengan"type": "module"dipackage.json, atau fitur-fitur terbaru seperti top-level await hanya ada di v14.8+. Cara memastikan: jalankannode --versiondan cross-check dengan dokumentasi fitur yang kamu gunakan.Asynchronous code tanpa error handling — Penyebab
UnhandledPromiseRejection. Banyak developer menggunakan.then()tanpa.catch(), atauawaittanpatry/catch, sehingga ketika Promise gagal, error-nya "menggantung" tanpa penanganan. Cara memastikan: cari semua pemanggilan async di codebase dan verifikasi apakah setiap panggilan memiliki mekanisme catch.
Cara Memperbaiki
Perbaikan 1: Cannot find module
Langkah pertama, pastikan kamu berada di direktori proyek yang benar:
cd /path/to/your/project
npm install
Output yang diharapkan:
added 157 packages in 12s
Jika paket tertentu masih tidak ditemukan, install secara eksplisit:
npm install express
Jika kamu menggunakan monorepo atau workspace, pastikan paket ter-install di lokasi yang tepat. Verifikasi dengan:
node -e "console.log(require.resolve('express'))"
Output yang diharapkan menunjukkan path absolut ke modul, misalnya:
/home/user/project/node_modules/express/index.js
Fix permanen: Selalu jalankan npm install (atau npm ci di CI/CD) setelah setiap perubahan package.json. Tambahkan script postinstall jika diperlukan.
Perbaikan 2: EADDRINUSE
Temukan dan matikan proses yang memonopoli port:
Linux/macOS:
lsof -ti :3000 | xargs kill -9
Windows:
for /f "tokens=5" %a in ('netstat -ano ^| findstr :3000') do taskkill /PID %a /F
Output yang diharapkan:
Killed
Atau, lebih elegan, ubah port aplikasimu ke port yang kosong:
PORT=3001 node server.js
Verifikasi dengan menjalankan ulang aplikasi dan pastikan tidak ada error EADDRINUSE lagi. Aplikasi seharusnya log: Server listening on port 3001.
Fix permanen: Gunakan tool seperti kill-port sebagai script pre-start, atau konfigurasi aplikasi untuk otomatis mencari port yang available.
Perbaikan 3: ENOENT
Jangan gunakan relative path berbasis CWD. Ganti:
// ❌ Rentan error karena bergantung pada CWD
const config = require('./config.json');
dengan:
// ✅ Menggunakan __dirname sebagai referensi stabil
const config = require(path.join(__dirname, 'config.json'));
Atau jika menggunakan ES Module:
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const config = JSON.parse(readFileSync(join(__dirname, 'config.json'), 'utf-8'));
Verifikasi dengan menjalankan aplikasi dari berbagai direktori dan memastikan file selalu ditemukan.
Perbaikan 4: SyntaxError Unexpected token
Jika kamu ingin menggunakan ES Module, tambahkan di package.json:
{
"type": "module"
}
Atau rename file dari .js ke .mjs. Jika sebaliknya kamu ingin tetap di CommonJS, gunakan require() dan module.exports saja.
Verifikasi:
node --input-type=module -e "import('fs').then(m => console.log('ESM OK'))"
Output: ESM OK
Perbaikan 5: UnhandledPromiseRejection
Bungkus setiap operasi async dengan error handling:
// ❌ Tanpa handler
const data = await fetch('/api/users');
// ✅ Dengan try/catch
try {
const data = await fetch('/api/users');
} catch (error) {
console.error('Gagal mengambil data:', error.message);
}
Sebagai safety net global, tambahkan di entry point aplikasi:
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection:', reason);
// Lakukan graceful shutdown jika perlu
process.exit(1);
});
Verifikasi: sengaja throw error di dalam Promise dan pastikan aplikasi menangkapnya dengan benar alih-alih crash tanpa pesan.
Supaya Tidak Terulang
Pencegahan selalu lebih murah daripada perbaikan. Berikut konfigurasi dan best practice yang bisa meminimalkan error-error di atas kembali muncul.
Konfigurasi package.json yang robust:
{
"type": "commonjs",
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"prestart": "node -e \"const v=process.versions.node.split('.').map(Number); if(v[0]<18) { console.error('Butuh Node >=18'); process.exit(1); }\"",
"start": "node server.js"
}
}
Dengan konfigurasi engines, kamu memaksa versi Node.js minimum. Ditambah script prestart yang memvalidasi versi sebelum aplikasi berjalan, error karena sintaks yang tidak didukung bisa dicegah sejak awal.
Gunakan .nvmrc untuk konsistensi versi di tim:
18.17.0
Semua member tim tinggal menjalankan nvm use dan versi Node.js akan otomatis sesuai.
Untuk masalah port, gunakan environment variable dengan fallback:
const PORT = process.env.PORT || 0; // Port 0 = OS otomatis assign port kosong
const server = app.listen(PORT, () => {
console.log(`Server berjalan di port ${server.address().port}`);
});
Menggunakan port 0 adalah trik yang kurang dikenal tapi sangat efektif: OS akan otomatis mencarikan port yang available, sehingga EADDRINUSE tidak akan pernah terjadi lagi saat development.
Best practice tambahan:
- Selalu commit
package-lock.jsonke repository agar setiapnpm cimenghasilkan dependency tree yang identik. - Gunakan
npm cialih-alihnpm installdi environment CI/CD karenanpm cimelakukan clean install berdasarkan lock file dan akan error jika lock file tidak sinkron denganpackage.json—ini mencegah inkonsistensi modul. - Pasang
eslintdengan ruleno-unhandled-promisesuntuk mendeteksi Promise yang tidak ditangani sebelum kode mas