Operasi berkas adalah salah satu sumber error yang paling sering kita jumpai: berkas yang dibaca sudah dipindahkan orang lain, folder yang mau dibuat ternyata sudah ada, path yang dituju menolak diakses. Kegagalan seperti ini bukan bug — merupakan kondisi normal yang harus diantisipasi program yang matang. Kabar baiknya, error filesystem di Node.js datang dengan label yang sangat terbaca: properti code seperti ENOENT atau EEXIST yang menyebut penyebabnya secara persis. Pada chapter penutup section ini kita belajar membaca label tersebut dan menyusun pola penanganan yang rapi.
Error pada API Promise #
Pada node:fs/promises, kegagalan operasi berarti promise yang reject. Bentuk penanganannya adalah try...catch seperti error JavaScript pada umumnya — dengan satu tambahan penting: object error filesystem memiliki properti code yang berisi kode standar dari sistem operasi.
import { readFile, mkdir, rm } from "node:fs/promises";
async function coba(label, aksi) {
try {
await aksi();
console.log(`${label}: sukses`);
} catch (e) {
console.log(`${label}: kode=${e.code}`);
console.log(` pesan: ${e.message}`);
}
}
await coba("baca berkas yang tidak ada", () =>
readFile("berkas-tiada.txt", "utf8"));
await coba("baca direktori sebagai berkas", () =>
readFile(".", "utf8"));
await rm("folder-uji", { recursive: true, force: true });
await coba("mkdir pertama", () => mkdir("folder-uji"));
await coba("mkdir kedua tanpa recursive", () => mkdir("folder-uji"));
await rm("folder-uji", { recursive: true, force: true });
console.log("folder-uji dibersihkan");Output yang Dihasilkan:
baca berkas yang tidak ada: kode=ENOENT
pesan: ENOENT: no such file or directory, open 'berkas-tiada.txt'
baca direktori sebagai berkas: kode=EISDIR
pesan: EISDIR: illegal operation on a directory, read
mkdir pertama: sukses
mkdir kedua tanpa recursive: kode=EEXIST
pesan: EEXIST: file already exists, mkdir 'folder-uji'
folder-uji dibersihkanMari kita telaah bagian-bagian pentingnya:
- Baris 3-11 (function
coba): helper kecil ini menjalankan operasi apa pun di dalamtry...catchdan mencetak hasilnya. Pola ini menjadikan contoh ringkas sekaligus menunjukkan bentuk asli penanganan error promise. - Baris 13-14 (membaca berkas yang tidak ada): operasi gagal dengan
codebernilaiENOENT(Error NO ENTry — entri tidak ditemukan). Pesannya menyebut path relatif yang kita tulis, sehingga mudah diperiksa. - Baris 16-17 (membaca direktori):
readFilehanya untuk berkas; diberi path direktori, operasi gagal denganEISDIR(is a directory). - Baris 19-21 (mkdir dua kali): panggilan pertama berhasil; panggilan kedua pada path yang sama gagal dengan
EEXISTkarena tanparecursive: true,mkdirmenolak folder yang sudah ada. - Baris 19 (
rmber-forcedi awal skenario): pembersihan ini menjamin kondisi awal — folder pasti tidak ada — sehingga urutan sukses/gagal selalu sama berapa pun kali contoh dijalankan.
Selain code, error filesystem juga membawa properti pelengkap seperti path (path yang dituju) dan syscall (nama operasi sistem yang gagal, misalnya open). Ketiganya membuat error dapat didiagnosis tanpa harus menebak dari stack trace.
Kode Error yang Sering Dijumpai #
Kode error berasal dari konvensi sistem operasi, jadi daftarnya panjang — tetapi enam berikut menutup mayoritas kasus sehari-hari:
| Kode | Artinya | Contoh pemicu |
|---|---|---|
ENOENT | Berkas atau direktori tidak ada | Membaca berkas yang belum dibuat atau sudah dipindahkan |
EEXIST | Target sudah ada | mkdir tanpa recursive pada folder yang sudah ada; writeFile dengan flag wx |
EISDIR | Operasi diberikan ke direktori, padahal butuh berkas | readFile pada path direktori |
ENOTDIR | Sebaliknya: operasi butuh direktori, yang diberi berkas | readdir pada path berkas |
ENOTEMPTY | Direktori tidak kosong | rmdir pada folder yang masih berisi (gunakan rm recursive) |
EACCES / EPERM | Akses ditolak atau operasi tidak diizinkan | Path milik pengguna lain, berkas terkunci, sistem berkas hanya-baca |
Daftar resmi beserta penjelasannya terdapat di dokumentasi error Node.js
. Properti code inilah kunci pola berikutnya: daripada membandingkan teks pesan — yang bisa berubah antar versi dan berbeda bahasanya per sistem operasi — kita cukup memeriksa kodenya.
Pola Helper: Tangani yang Diharapkan, Lempar Ulang Sisanya #
Membaca kode saja tidak cukup; yang menentukan kualitas kode adalah keputusan apa yang kita lakukan setelah error tertangkap. Prinsipnya satu: tangani hanya error yang memang kita antisipasi dan punya rencana padanya; error lain diteruskan ke pemanggil agar tidak ada kegagalan yang tertelan diam-diam.
import { readFile, writeFile, rm } from "node:fs/promises";
async function bacaKonfigurasi(namaBerkas) {
try {
const isi = await readFile(namaBerkas, "utf8");
return JSON.parse(isi);
} catch (e) {
// Hanya error yang kita antisipasi yang ditangani di sini
if (e.code === "ENOENT") {
console.log(`${namaBerkas} tidak ditemukan, pakai nilai bawaan`);
return { tema: "terang", bahasa: "id" };
}
// Error lain diteruskan ke pemanggil
throw e;
}
}
const a = await bacaKonfigurasi("konfigurasi-tiada.json");
console.log(`tema bawaan : ${a.tema}`);
await writeFile("konfigurasi-uji.json", JSON.stringify({ tema: "gelap" }));
const b = await bacaKonfigurasi("konfigurasi-uji.json");
console.log(`tema tersimpan : ${b.tema}`);
await rm("konfigurasi-uji.json");
// Error di luar dugaan tetap terdengar sampai ke pemanggil
try {
await bacaKonfigurasi(".");
} catch (e) {
console.log(`diteruskan ke pemanggil: ${e.code}`);
}Output yang Dihasilkan:
konfigurasi-tiada.json tidak ditemukan, pakai nilai bawaan
tema bawaan : terang
tema tersimpan : gelap
diteruskan ke pemanggil: EISDIRFunction bacaKonfigurasi mengembalikan nilai bawaan hanya untuk ENOENT — kondisi yang wajar bagi berkas konfigurasi opsional. Error lain, seperti EISDIR ketika path ternyata direktori atau SyntaxError ketika isi berkas bukan JSON sah, tetap dilempar ke atas: pemanggil melihat kegagalan aslinya dan bisa memutuskan sendiri. Bila seluruh error ditelan di satu tempat, program berjalan dengan hasil yang salah tanpa jejak untuk diperiksa — kelas bug yang paling melelahkan dicari.
Error pada Gaya Callback dan Sync #
Dua gaya API lain menangani error dengan bentuk berbeda, dan keduanya sudah kita sapa di awal section ini. Pada gaya callback, error datang lewat parameter pertama (error-first), sehingga pemeriksaan wajib berada di baris pertama callback:
import { readFile } from "node:fs";
readFile("berkas-tiada.txt", "utf8", (err, data) => {
if (err) {
console.error(`gagal membaca: ${err.code}`);
return;
}
console.log(data.trim());
});Pada gaya synchronous, error dilempar begitu operasi dijalankan, jadi try...catch yang sama seperti versi promise dapat dipakai — cukup tanpa await. Perbedaan strukturnya hanya pada penempatan: catch menangkap error yang lempar langsung, bukan hasil promise yang reject.
Dengan pola ini, kita menutup Section Filesystem secara lengkap: dari mengenal module fs, membaca dan menulis berkas, mengelola direktori, membaca metadata, memantau perubahan, sampai menangani kegagalannya dengan rapi. Perjalanan berikutnya masuk ke bahan dasar yang selama ini bekerja di balik layar: Buffer dan stream — cara Node.js mengolah data berukuran besar secara bertahap tanpa memboroskan memori.