Advanced (Diperbarui: 3/6/2026)

Pola Error Handling dengan Claude Code: klasifikasikan kegagalan di boundary

Panduan Claude Code untuk error handling: validasi API, API eksternal, job batch, TypeScript, dan strategi recovery.

Pola Error Handling dengan Claude Code: klasifikasikan kegagalan di boundary

Error handling bukan berarti menambah try-catch di semua tempat. Kalau kita hanya meminta Claude Code “tolong perbaiki error ini”, hasilnya sering terlalu umum: semua kegagalan menjadi 500, log sulit dicari, dan tidak jelas apakah user harus memperbaiki input, menunggu layanan eksternal, atau menjalankan ulang job.

Pola yang lebih kuat adalah mengklasifikasikan kegagalan di boundary dan menulis jalur recovery secara eksplisit. Boundary adalah titik ketika aplikasi bertemu sesuatu yang tidak sepenuhnya kita kontrol: request body API, payment provider, CRM, layanan email, scheduled job, import CSV, atau layar frontend. Saat boundary jelas, Claude Code bisa membuat patch yang lebih aman: validasi mengembalikan 400, kegagalan eksternal sementara bisa retry, dan batch failure disimpan agar dapat dijalankan ulang.

Artikel ini dibuat untuk pemula, tetapi tetap dekat dengan kebutuhan produksi. Ada contoh TypeScript yang bisa langsung dijalankan, tiga use case, jebakan umum, prompt review Claude Code, referensi resmi, dan CTA untuk mengubah pola ini menjadi materi training atau produk.

Mulai dari recovery, bukan nama class

Sebelum memilih nama AppError atau DomainError, tanyakan dulu: setelah gagal, sistem harus melakukan apa?

BoundaryContohResponsRecovery
Validasi APIEmail salah, angka di luar rentang, JSON rusak400User memperbaiki input
API eksternalPayment, CRM, email, analytics down502 atau 503Retry, pause, tampilkan error sementara
Job/BatchLaporan malam, import CSV, kirim notifikasiCatatan gagal internalRerun aman, failure queue, alert

message yang mudah dibaca saja tidak cukup. Program perlu field seperti kind, code, retryable, dan status untuk mengambil keputusan. Claude Code juga lebih mudah mereview perilaku dibanding menebak maksud dari teks bebas.

Contoh TypeScript yang bisa dijalankan

Contoh berikut berjalan di Node.js 18 atau lebih baru. Kita memakai tsx untuk menjalankan TypeScript langsung. Tidak ada panggilan API nyata, karena fetcher disuntikkan agar failure path mudah diuji.

npm install -D tsx typescript
npx tsx error-patterns-demo.ts
type Kind = "validation" | "external" | "job";
type AppError = { kind: Kind; code: string; message: string; retryable: boolean; status: number; detail?: unknown };
type Result<T> = { ok: true; value: T } | { ok: false; error: AppError };

const ok = <T>(value: T): Result<T> => ({ ok: true, value });
const fail = <T>(error: AppError): Result<T> => ({ ok: false, error });

function parseUser(body: unknown): Result<{ email: string; age: number }> {
  if (typeof body !== "object" || body === null) {
    return fail({ kind: "validation", code: "BODY_REQUIRED", message: "body must be an object", retryable: false, status: 400 });
  }
  const data = body as Record<string, unknown>;
  if (typeof data.email !== "string" || !data.email.includes("@")) {
    return fail({ kind: "validation", code: "EMAIL_INVALID", message: "email is invalid", retryable: false, status: 400 });
  }
  if (typeof data.age !== "number" || data.age < 13) {
    return fail({ kind: "validation", code: "AGE_INVALID", message: "age must be 13 or greater", retryable: false, status: 400 });
  }
  return ok({ email: data.email, age: data.age });
}

async function callPartner(fetcher: () => Promise<Response>): Promise<Result<{ id: string }>> {
  try {
    const response = await fetcher();
    if (!response.ok) {
      return fail({ kind: "external", code: "PARTNER_HTTP", message: `partner returned ${response.status}`, retryable: response.status >= 500, status: 503 });
    }
    const json = (await response.json()) as { id?: unknown };
    if (typeof json.id !== "string") {
      return fail({ kind: "external", code: "PARTNER_PAYLOAD", message: "partner payload is invalid", retryable: false, status: 502, detail: json });
    }
    return ok({ id: json.id });
  } catch (error) {
    return fail({ kind: "external", code: "PARTNER_UNREACHABLE", message: "partner is unreachable", retryable: true, status: 503, detail: error });
  }
}

async function runJob<T>(name: string, work: () => Promise<T>, retries = 2): Promise<Result<T>> {
  for (let attempt = 1; attempt <= retries + 1; attempt += 1) {
    try {
      return ok(await work());
    } catch (error) {
      if (attempt <= retries) continue;
      return fail({ kind: "job", code: "JOB_FAILED", message: `${name} failed`, retryable: true, status: 500, detail: { attempt, error } });
    }
  }
  return fail({ kind: "job", code: "JOB_FAILED", message: `${name} failed`, retryable: true, status: 500 });
}

console.log(parseUser({ email: "bad", age: 10 }));
console.log(await callPartner(async () => new Response("down", { status: 503 })));
console.log(await runJob("daily-report", async () => ({ exportedRows: 42 })));

Use case 1: validasi input API

Kegagalan validasi biasanya bisa diperbaiki oleh user. Email tidak valid, usia terlalu kecil, JSON bukan object, atau plan tidak dikenal bukanlah crash server. Di contoh, parseUser mengklasifikasikan kegagalan sebagai validation, mengembalikan 400, dan memberi retryable: false.

Hasilnya lebih mudah dipakai. Frontend bisa menyorot field yang salah, backend bisa mencari log dengan EMAIL_INVALID, dan Claude Code bisa menambah test untuk jalur gagal. Untuk memperluasnya, baca juga API testing dengan Claude Code dan strategi testing Claude Code.

Use case 2: kegagalan API eksternal

Layanan eksternal bisa gagal walau kode kita benar. Payment, email, CRM, spreadsheet, dan analytics bisa timeout, rate limit, atau memberi payload aneh. Hal paling penting adalah memisahkan failure yang layak retry dari failure yang tidak boleh retry.

Di contoh, 5xx dianggap retryable: true, tetapi payload dengan bentuk salah menjadi retryable: false. Me-retry payload rusak hanya membuat queue dan log penuh. Untuk semantik respons HTTP, lihat MDN Response.ok. Jika memakai Express, cek juga Express error handling.

Use case 3: kegagalan job dan batch

Job sering gagal ketika user tidak lagi melihat layar. Laporan malam, import CSV, invoice, dan pengiriman notifikasi perlu meninggalkan jejak yang bisa dipakai untuk rerun. runJob menyimpan nama job, attempt terakhir, dan apakah error bisa diulang. Di produksi, data ini sebaiknya masuk ke structured log, failure queue, admin screen, atau alert.

Pertanyaan terpenting adalah idempotency: apakah aman dijalankan ulang? Jika import CSV membuat baris duplikat, retry menjadi berbahaya. Jika job billing menagih dua kali, error handling berubah menjadi incident. Minta Claude Code mereview replay safety, bukan hanya syntax.

Jebakan umum

Jebakan pertama adalah catch { return null; }, karena bukti kegagalan hilang. Jebakan kedua adalah membocorkan stack trace, nama SQL, environment variable, path internal, atau potongan token ke user. Untuk sisi keamanan, baca audit keamanan dengan Claude Code. Jebakan ketiga adalah retry semua error. Validation error dan payload salah tidak akan membaik hanya karena menunggu.

Jebakan lain adalah membuat tipe rapi tanpa aturan tim. TypeScript narrowing dan discriminated union membantu, tetapi besok seseorang bisa kembali menulis throw new Error("failed"). Pakai referensi resmi TypeScript Narrowing, lalu tulis aturan boundary di AGENTS.md atau CLAUDE.md.

Prompt review untuk Claude Code

Review error handling di PR ini.
Cek:
1. Failure diklasifikasikan di boundary API input, API eksternal, dan job/batch.
2. Error yang bisa diperbaiki user tidak menjadi 500.
3. retryable dan non-retryable dipisahkan.
4. Response tidak membocorkan stack trace, SQL, secret, atau path internal.
5. Log menyimpan code, kind, attempt, dan cause yang aman.
6. Ada minimal 3 test untuk failure path.
Berikan patch paling kecil yang aman dan test pendukungnya.

Untuk mengunci failure path, Node.js test runner sering cukup. Pengaturan dan project memory Claude Code bisa dicek dari Claude Code overview. Jika ingin mulai dari test, lanjutkan ke TDD dengan Claude Code dan teknik debugging Claude Code.

CTA dan hasil uji Masa

Error handling cocok untuk training tim karena menghubungkan API, log, security, test, dan operasi. Untuk mulai sendiri, ambil cheat sheet gratis. Jika butuh prompt, checklist review, dan template siap tim, lihat produk. Untuk memperbaiki repository yang sudah berjalan, halaman training dan konsultasi Claude Code bisa membantu memetakan boundary API, integrasi eksternal, dan batch.

Di workflow Masa, menyatukan validation, external API, dan batch failure ke bentuk mirip AppError membuat prompt jauh lebih pendek. Dulu instruksinya “perbaiki error ini”; sekarang bisa “validation return 400, external pakai retryable, job simpan attempt”. Review pun fokus ke response, log, dan test. Ini bukan arsitektur ajaib, tetapi jauh lebih mudah dioperasikan daripada banyak 500 anonim.

#Claude Code #error handling #design patterns #TypeScript #robustness
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.