Belajar PowerShell - Error Handling
Episode 12 of 31

Belajar PowerShell - Error Handling

Kuasai penanganan error di PowerShell: pahami perbedaan error terminating dan non-terminating, bangun blok try-catch-finally yang solid, pilih throw atau Write-Error, atur perilaku lewat variabel otomatis, dan terapkan praktik terbaik untuk skrip yang siap produksi.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Di episode 11 kalian menguasai regular expressions — pola teks untuk menyaring, memvalidasi, dan mengekstrak data. Tapi ada satu fakta yang tidak bisa dihindari: sebaik apa pun pola kalian, skrip tetap bisa gagal. File hilang, server mati, permission ditolak. Pertanyaan yang benar bukan apakah skrip akan error, melainkan bagaimana kalian meresponsnya.

Episode ini membahas error handling secara menyeluruh: error terminating versus non-terminating, anatomi error record dan exception, blok try/catch/finally, memilih throw atau Write-Error, mengendalikan perilaku lewat $ErrorActionPreference dan -ErrorAction, serta riwayat error di $Error.

Error Terminating vs Non-Terminating

Bayangkan kalian mengirim karton berisi sepuluh paket lewat kurir. Ada dua jenis kegagalan yang berbeda. Yang pertama: satu paket di dalam karton penyok — kurir mencatatnya, tapi tetap mengantarkan sembilan paket lainnya. Yang kedua: alamat seluruh karton salah — pengiriman berhenti total.

Dua kegagalan itu persis memetakan dua tipe error di PowerShell:

  • Non-terminating error — perintah menemukan masalah pada satu item, menulis error record ke aliran error, lalu melanjutkan ke item berikutnya. Contoh klasik: meminta Get-Content untuk beberapa file di mana salah satunya tidak bisa dibuka. Perintah tidak berhenti; ia menampilkan error dan tetap membaca file lain.
  • Terminating error — error fatal yang menghentikan eksekusi. Contohnya throw, atau exception .NET seperti membagi angka dengan nol. Tanpa penanganan, skrip berhenti di titik itu.

Kenapa pembagian ini penting? Karena blok try/catch hanya menangkap error terminating dengan andal. Error non-terminating biasanya "bocor" melewati try/catch tanpa tertangkap — inilah sumber kebingungan terbesar. Perhatikan perbedaannya saat dijalankan:

Non-terminating: eksekusi tetap lanjut
Get-Content file-ada.txt, file-hilang.txt
Write-Host "Baris ini tetap dicetak"
Terminating: eksekusi berhenti
throw "Koneksi database gagal"
Write-Host "Baris ini tidak pernah dicetak"

Pada contoh pertama, Get-Content menampilkan error untuk file yang hilang, tapi Write-Host tetap dijalankan. Pada contoh kedua, throw menghentikan skrip sehingga baris berikutnya tidak pernah dieksekusi.

Error Record dan Exception

Setiap error di PowerShell adalah objek ErrorRecord — bungkusan berisi pesan, kategori error, target objek, dan exception yang mendasarinya. Non-terminating dan terminating sama-sama menghasilkan error record; yang berbeda hanya perilakunya terhadap pipeline.

Exception adalah objek .NET yang terbungkus di dalam record. Properti Exception menyimpan detail penyebab, dan tipe exception-nya — misalnya System.IO.FileNotFoundException — menjadi kunci untuk menangkap error yang spesifik. Cara melihat detailnya: isi variabel otomatis $Error[0] yang selalu menyimpan error terbaru — akan dibahas dalam bentuk kode di bagian bawah episode.

Blok try-catch-finally

Struktur penanganan error di PowerShell adalah blok try yang membungkus kode berisiko, catch untuk merespons kegagalan, dan finally untuk pembersihan. Bentuk paling dasar:

Struktur dasar try-catch
try {
    $isi = Get-Content "/etc/hosts" -ErrorAction Stop
    Write-Host "Berhasil membaca $($isi.Count) baris"
}
catch {
    Write-Host "Gagal membaca file: $($_.Exception.Message)"
}

Di dalam blok catch, variabel otomatis $_ menunjuk ke error record yang sedang ditangani — dari situlah $_.Exception.Message diambil.

Menangkap Exception Spesifik

Analogikan dengan sistem alarm: satu alarm besar yang berbunyi untuk segala gangguan sulit ditangani karena kita tidak tahu sumber masalahnya. Lebih baik kenali tipe exception-nya satu per satu, lalu biarkan satu catch umum sebagai jaring pengaman terakhir.

Menangkap tipe exception spesifik
try {
    $data = Invoke-RestMethod "https://api.contoh.com/data" -ErrorAction Stop
}
catch [System.Net.WebException] {
    Write-Host "Masalah jaringan - cek koneksi."
}
catch [System.UnauthorizedAccessException] {
    Write-Host "Token tidak valid."
}
catch {
    Write-Host "Error tak terduga: $($_.Exception.Message)"
}

Urutan catch diperiksa dari atas ke bawah. Tulis blok yang paling spesifik lebih dulu, dan simpan catch tanpa tipe di paling akhir sebagai cadangan.

finally untuk Pembersihan

Blok finally dijalankan selalu, tanpa peduli apakah try sukses atau catch menangkap error. Ini tempat yang tepat untuk pembersihan: menutup koneksi, menghapus file sementara, atau mengembalikan state. Seperti bulu pensil yang tetap terhapus baik hasil tulisan bagus maupun salah.

finally - pembersihan yang dijamin jalan
$file = [System.IO.File]::OpenWrite("/tmp/catatan.txt")
try {
    $file.WriteByte(65)
}
catch {
    Write-Host "Gagal menulis ke file."
}
finally {
    $file.Close()
    Write-Host "Handle file ditutup."
}

Jika try sukses, catch dilewati; jika error terjadi, catch menanganinya — dan dalam kedua kasus finally tetap berjalan. Tanpa finally, resource yang sedang dibuka akan menggantung menjadi kebocoran.

try-catch Bersarang

Terkadang satu level tidak cukup: kalian perlu menangani kegagalan pada tahap tertentu secara lokal, namun tetap membiarkan error yang lebih serius naik ke level atas. Seperti petugas pintu yang menangani tamu biasa, tetapi memanggil keamanan untuk tamu yang membahayakan.

Nested try-catch dengan rethrow
try {
    Copy-Item "/data/produksi.db" "/backup/produksi.db" -ErrorAction Stop
    try {
        Invoke-Sqlcmd -Query "SELECT 1" -ErrorAction Stop
    }
    catch {
        Write-Host "Query gagal, mencoba lagi..."
    }
}
catch {
    Write-Host "Backup gagal - membatalkan operasi."
    throw
}

Perhatikan throw tanpa argumen di catch terluar — ia mengirim ulang error yang sedang ditangani ke pemanggil berikutnya. Inilah pola rethrow: catat di lapisan ini, biarkan lapisan atas memutuskan nasib akhir.

throw vs Write-Error

Dua cara utama memunculkan error buatan: throw dan Write-Error.

  • throw menghasilkan error terminating — cocok untuk kode yang memang harus berhenti (fungsi, logika validasi). Ia juga menjadi sarana rethrow di dalam catch.
  • Write-Error menulis error record ke aliran error tanpa menghentikan eksekusi — error bersifat non-terminating. Cocok untuk melaporkan masalah pada satu item namun tetap melanjutkan proses lain.
throw vs Write-Error
function Test-Port {
    param($Port)
    if ($Port -lt 1 -or $Port -gt 65535) {
        throw "Port $Port di luar rentang 1-65535"
    }
    Write-Output "Port $Port valid"
}

Aturan praktis: gunakan throw untuk kegagalan yang harus menghentikan alur, dan Write-Error untuk kegagalan satu item yang boleh dilewati.

$ErrorActionPreference dan -ErrorAction

Selain memutuskan di level perintah, kalian bisa mengubah perilaku default error non-terminating di level sesi melalui variabel otomatis $ErrorActionPreference.

NilaiPerilaku
ContinueTampilkan error, lanjutkan (default)
SilentlyContinueSembunyikan error, lanjutkan
StopPerlakukan semua error sebagai terminating
IgnoreSembunyikan error dan jangan catat ke $Error

Nilai -ErrorAction pada sebuah perintah (misal Get-Item -ErrorAction SilentlyContinue) selalu menimpa preferensi global untuk satu pemanggilan itu saja. Ignore unik karena error tidak ditampilkan dan tidak direkam ke $Error — paling hemat resource jika kalian memang tidak peduli pada error tersebut.

Important

Jangan pernah mengeset $ErrorActionPreference = "Stop" tanpa alasan di skrip produksi. Perubahan global ini membuat perintah-perintah lain ikut berperilaku terminating — termasuk yang awalnya aman. Akibatnya, satu file yang tidak ada bisa menghentikan seluruh pipeline. Jika hanya butuh error terminating pada satu perintah, gunakan -ErrorAction Stop secara eksplisit, atau batasi perubahan di dalam sebuah blok kecil dan kembalikan nilai sebelumnya.

Variabel Otomatis $Error

Sesi PowerShell menyimpan seluruh riwayat error ke variabel otomatis $Error, yang berupa daftar. Konvensinya: $Error[0] selalu berisi error terbaru, $Error[1] yang lebih lama, dan seterusnya — indeks berjalan mundur dari waktu.

Membaca dan membersihkan riwayat error
Get-Item file-tidak-ada.txt -ErrorAction SilentlyContinue
$Error.Count
$Error[0].Exception.Message
$Error.Clear()
$Error.Count

$Error.Clear() mengosongkan riwayat — berguna di awal tes atau skrip agar hanya error dari sesi tersebut yang dihitung.

Praktik Terbaik Error Handling

Praktik yang bisa kalian terapkan hari ini:

  • Gunakan -ErrorAction Stop bila ingin try/catch menangkap error dari cmdlet — tanpa itu, mayoritas error cmdlet bersifat non-terminating dan lolos dari catch.
  • Tangkap exception spesifik sebelum yang umum — urutkan catch dari tipe paling spesifik ke catch umum paling akhir.
  • Selalu sediakan finally untuk resource — file, koneksi, session — agar tidak bocor saat terjadi error.
  • Jangan set $ErrorActionPreference = "Stop" secara global di skrip produksi.
  • Tulis pesan error yang bisa ditindaklanjuti — sertakan nama resource dan konteks.

Penutup

Episode ini mengubah error dari musuh yang misterius menjadi kejadian yang terkendali: kalian kini memahami error terminating yang menghentikan eksekusi versus non-terminating yang hanya melaporkan; membedah error record dan exception; membangun try/catch/finally dengan penangkapan exception spesifik, finally untuk pembersihan, dan try-catch bersarang dengan pola rethrow; memilih throw atau Write-Error sesuai konteks; mengendalikan perilaku global lewat $ErrorActionPreference dan parameter -ErrorAction; serta membaca riwayat error dengan $Error.

Poin kunci yang dibawa pulang:

  • try/catch hanya menangkap error terminating — tambahkan -ErrorAction Stop bila perlu.
  • finally dijamin berjalan, di situlah pembersihan resource.
  • Urutkan catch dari exception spesifik ke umum.
  • $Error[0] adalah error terbaru; $Error.Clear() membersihkan riwayat.

Skrip yang tahan banting adalah skrip yang tahu harus berbuat apa saat segalanya salah. Di episode 13 kita mengorganisasi kode kalian ke dalam unit yang bisa dibagikan: PowerShell Modules — script module, manifest, PowerShell Gallery, hingga cara membuat modul kalian sendiri. Sampai jumpa di episode 13!

Belajar PowerShell - Error Handling | Belajar PowerShell