Membaca Error Messages — Debugging

Cara Membaca Error Messages Kemampuan membaca error message dengan benar adalah skill debugging paling fundamental. Error message memberitahu kamu apa yang…

Cara Membaca Error Messages

Kemampuan membaca error message dengan benar adalah skill debugging paling fundamental. Error message memberitahu kamu apa yang salah, di mana, dan seringkali mengapa.

Anatomi Error Message

Uncaught TypeError: Cannot read properties of undefined (reading "name")
    at UserProfile (UserProfile.jsx:15:23)
    at renderWithHooks (react-dom.development.js:14985:18)
    at mountIndeterminateComponent (react-dom.development.js:17811:13)

Komponen:

  1. Error type: TypeError
  2. Error message: Cannot read properties of undefined (reading "name")
  3. Stack trace: urutan function calls yang mengarah ke error
  4. Location: UserProfile.jsx:15:23 (file, baris, kolom)

Jenis Error Umum di JavaScript

TypeError

Operasi pada tipe data yang salah:

// Cannot read properties of undefined
const user = undefined;
console.log(user.name);  // ❌ TypeError!
// Fix: cek dulu apakah user ada
console.log(user?.name);  // ✅ undefined (tanpa error)

// ... is not a function
const angka = 42;
angka();  // ❌ TypeError: angka is not a function
// Fix: angka bukan function, jangan dipanggil

// Cannot set properties of null
document.getElementById("tidak-ada").textContent = "hi";
// Fix: cek dulu apakah element ada
const el = document.getElementById("tidak-ada");
if (el) el.textContent = "hi";

ReferenceError

Mengakses variabel yang belum dideklarasi:

console.log(namaUser);  // ❌ ReferenceError: namaUser is not defined
// Fix: deklarasikan dulu
const namaUser = "Budi";

// Juga bisa terjadi karena scope
function outer() {
  const x = 10;
}
console.log(x);  // ❌ ReferenceError (x hanya ada di dalam outer)

SyntaxError

Kesalahan penulisan kode:

// Unexpected token
const obj = { name: "Budi", };  // Trailing comma OK di JS modern
JSON.parse("{ name: \"Budi\" }");  // ❌ SyntaxError: JSON membutuhkan key dalam quotes

// Unexpected end of input
function hello() {
  console.log("hi");
// ❌ SyntaxError: kurung tutup lupa!

// Fix JSON:
JSON.parse('{"name": "Budi"}');  // ✅

RangeError

Nilai di luar range yang diizinkan:

const arr = new Array(-1);  // ❌ RangeError: Invalid array length
// Fix: length harus positif

function recursive() {
  recursive();  // ❌ RangeError: Maximum call stack size exceeded
}
// Fix: tambahkan base case untuk menghentikan recursion

Membaca Stack Trace

Stack trace dibaca dari atas ke bawah:

Error: Data tidak ditemukan
    at fetchUser (api.js:25:11)          ← error terjadi di sini
    at loadProfile (profile.js:10:5)     ← dipanggil dari sini
    at handleClick (app.js:45:3)         ← yang dipanggil dari sini
    at HTMLButtonElement.onclick (index.html:12:1)

Baris paling atas adalah tempat error terjadi. Baris di bawahnya menunjukkan chain of calls yang mengarah ke sana. Biasanya kamu fokus pada baris yang ada di kode kamu (bukan di library).

Error di Async Code

Unhandled Promise Rejection: TypeError: Failed to fetch
    at fetchData (api.js:5:18)
    at async loadPage (page.js:12:20)

Untuk async error, pastikan kamu selalu menggunakan try/catch:

// ❌ Error tidak tertangkap
async function loadData() {
  const response = await fetch("/api/data");
  const data = await response.json();
}

// ✅ Error tertangkap dan ditangani
async function loadData() {
  try {
    const response = await fetch("/api/data");
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Gagal load data:", error.message);
    return null;
  }
}

Tips Membaca Error

  1. Baca dari atas — error type dan message dulu
  2. Cari file kamu di stack trace — abaikan internal library
  3. Perhatikan baris dan kolom — langsung ke lokasi error
  4. Google error message — kemungkinan besar orang lain pernah mengalami
  5. Jangan panik melihat stack trace panjang — fokus pada baris teratas yang relevan

Reading Minified Stack Traces

Di production, kode di-minify (variable userName jadi a, function validateOrder jadi q). Stack trace jadi cryptic:

TypeError: Cannot read properties of undefined (reading "a")
    at q (app.min.js:1:48291)
    at r (app.min.js:1:49012)
    at HTMLButtonElement.<anonymous> (app.min.js:1:51203)

Tanpa konteks, "function q baris 1 kolom 48291" tidak bisa didebug. Source maps adalah jawabannya — file .map berisi mapping dari posisi minified ke file source asli + baris + kolom sebelum minify.

Aktifkan Source Maps di DevTools

Chrome DevTools sudah otomatis baca source map kalau bundle-nya punya comment:

//# sourceMappingURL=app.min.js.map

Kalau belum aktif: Settings (ikon gear) → Sources → centang:

Setelah aktif, stack trace di console dan breakpoint di Sources akan menunjuk ke kode source asli, bukan minified.

Source Map Strategies di Production

Deploy .map public = siapa saja bisa download kode asli kamu. Ada beberapa strategi aman:

Strategi Cara Kapan Dipakai
source-map Map file publik Open-source atau debugging terbuka
hidden-source-map Generate .map, tapi tidak ada comment sourceMappingURL Production — upload map ke Sentry/Datadog, bukan public
nosources-source-map Map ada tapi sourcesContent kosong Debug di DevTools tanpa kasih source code
eval-source-map Inline ke bundle (slow, dev only) Development mode

Pattern umum untuk production:

# Build dengan hidden-source-map
webpack --devtool hidden-source-map

# Upload map ke Sentry saat release
sentry-cli releases files $VERSION upload-sourcemaps ./dist

# Hapus .map dari server sebelum deploy
rm dist/*.map

Sentry/Datadog/Rollbar akan otomatis resolve stack trace minified ke kode asli saat menampilkan error — cuma untuk internal, tidak bocor ke public.

Yang akan kamu pelajari