Setiap proses yang berakhir meninggalkan satu angka terakhir kepada sistem operasi: exit code. Angka inilah yang dibaca shell, script CI, dan alat orchestrasi untuk memutuskan langkah berikutnya — melanjutkan tahap berikutnya atau langsung berhenti. Program yang lulus tapi melaporkan 1, atau gagal tapi melaporkan 0, akan menyesatkan seluruh rantai otomasi di atasnya. Pada chapter ini kita belajar mengatur exit code dengan process.exit(), memahami kode yang dihasilkan error tak tertangani, lalu memakai process.exitCode untuk pola yang lebih aman.

Konvensi Kode yang Saling Dipahami #

Nilai 0 berarti sukses; nilai lain berarti gagal — itulah seluruh kontraknya. Sistem operasi menyimpan kode ini sebagai bilangan 8-bit, sehingga rentang yang bermakna hanya 0 sampai 255; nilai di luar itu dipotong (misalnya process.exit(300) terbaca sebagai 44 oleh shell). Kode yang paling sering kita temui:

KodeArtiSiapa yang menghasilkannya
0suksesprogram berakhir normal
1kegagalan generikprocess.exit(1) atau error tak tertangani
2salah pemakaian (argumen tidak valid)konvensi banyak alat Unix
128 + nproses dihentikan oleh sinyal ndilaporkan shell, dibahas di chapter Signal dan Event Proses

Node.js sendiri tidak memaksa makna khusus untuk 2 ke atas; keputusan ada pada kita sebagai penulis program. Yang tidak bisa ditawar hanyalah 0 dan bukan-0.

Keluar dengan process.exit() #

Method process.exit(kode) mengakhiri proses seketika dengan kode pilihan kita. Pola yang umum: periksa syarat di awal program, tolak secepatnya bila tidak terpenuhi. Berkas gagal.mjs menolak berjalan tanpa argumen:

js
const [berkas] = process.argv.slice(2);

if (berkas === undefined) {
  console.error("nama berkas wajib diberikan");
  process.exit(1);
}

console.log(`memproses ${berkas}`);

Output yang Dihasilkan:

text
nama berkas wajib diberikan

Dua keputusan desain terlihat di sini. Pesan penolakan dikirim lewat console.error() ke stderr — sesuai disiplin stream pada chapter sebelumnya — sehingga hasil program tetap bersih untuk dipipa. Kemudian process.exit(1) dipanggil sebelum baris console.log terakhir sempat berjalan; itulah makna “seketika”: tidak ada langkah lain yang dieksekusi. Dari sisi shell, kode tersebut bisa diperiksa langsung lewat variable $? yang selalu berisi exit code perintah terakhir:

bash
node proses.mjs
echo kode: $?

Output yang Dihasilkan:

text
memproses data...
selesai: 3 tugas diperbarui
kode: 0

Berkas proses.mjs hanya mencetak dua baris dan berakhir normal dengan kode 0. Bandingkan dengan versi gagalnya — peringatan stderr sengaja dibuang agar baris kode kelihatan jelas:

bash
node gagal.mjs 2>/dev/null
echo kode: $?

Output yang Dihasilkan:

text
kode: 1

Shell juga memakai kode ini untuk merangkai perintah: perintah && lanjut hanya menjalankan lanjut bila kode 0, sedangkan || sebaliknya — sehingga node gagal.mjs || echo "gagal diproses" menjadi notifikasi error paling sederhana di dunia Unix.

Error Tak Tertangani Keluar dengan Kode 1 #

Kita tidak perlu memanggil process.exit() untuk setiap kegagalan. Error yang lolos tanpa tertangani menghentikan Node.js dengan exit code 1 secara otomatis, lengkap dengan laporan di stderr. Berkas lempar.mjs mensimulasikan error saat memuat konfigurasi:

js
const berkas = "konfigurasi.json";

throw new Error(`berkas ${berkas} tidak ditemukan`);

Output yang Dihasilkan:

text
throw new Error(`berkas ${berkas} tidak ditemukan`);
      ^

Error: berkas konfigurasi.json tidak ditemukan

Node.js v24.21.0

Laporan tersebut berisi baris kode yang melempar error, jenis dan pesannya, lalu versi Node.js — baris stack trace berpath absolut sudah dibersihkan dari tampilan di atas. Proses berakhir dengan kode 1 tanpa kita menulis satu baris penanganan pun. Untuk program CLI, perilaku bawaan ini justru sering diinginkan: gagal keras, gagal jelas. Tugas kita hanyalah memastikan pesan errornya cukup informatif untuk diperbaiki.

process.exitCode: Menunda Keputusan #

process.exit() punya satu kelemahan serius: ia memotong proses saat itu juga, termasuk penulisan stdout yang belum selesai dibilas ke pipa atau berkas. Alternatif yang lebih lembut adalah property process.exitCode — kita cukup menandai kode keluarnya, lalu membiarkan proses berakhir sendiri setelah seluruh pekerjaan selesai:

js
const [berkas] = process.argv.slice(2);

if (berkas === undefined) {
  process.exitCode = 1;
}

console.log("langkah 1 selesai");
console.log("langkah 2 selesai");
console.log(`berkas: ${berkas ?? "(tidak ada)"}`);

Output yang Dihasilkan:

text
langkah 1 selesai
langkah 2 selesai
berkas: (tidak ada)

Program kehabisan argumen dan kode keluarnya memang 1, tetapi ketiga baris console.log tetap tereksekusi sampai selesai — kebalikan dari process.exit(1) yang memotong di tengah jalan. Tidak ada output yang tertinggal di buffer, tidak ada pekerjaan setengah jadi yang ditinggalkan diam-diam.

Kode keluar melaporkan akhir yang kita rencanakan sendiri. Namun proses juga bisa diakhiri dari luar — oleh pengguna yang menekan Ctrl+C, atau oleh sistem yang mengirim sinyal penghentian. Mekanisme sinyal inilah yang kita tangani pada chapter berikutnya.

Referensi lanjutan untuk topik chapter ini: