Advanced (Aktualisiert: 3.6.2026)

Error-Handling-Patterns mit Claude Code: Fehler an Grenzen klassifizieren

Praxisguide fur Claude Code: API-Validierung, externe APIs, Jobs, TypeScript und klare Wiederherstellungspfade.

Error-Handling-Patterns mit Claude Code: Fehler an Grenzen klassifizieren

Error Handling bedeutet nicht, ueberall mehr try-catch einzubauen. Wenn Claude Code nur den Auftrag bekommt, “den Fehler zu reparieren”, entstehen oft unklare Patches: alles wird zu 500, Logs sind schwer zu durchsuchen, und niemand erkennt, ob der Nutzer die Eingabe korrigieren soll oder ob ein externer Dienst ausgefallen ist.

Das nuetzliche Muster lautet: Fehler an der Grenze klassifizieren und den Wiederherstellungspfad explizit machen. Eine Grenze ist dort, wo die Anwendung auf etwas trifft, das sie nicht voll kontrolliert: API-Request-Body, Zahlungsanbieter, CRM, E-Mail-Dienst, geplanter Job, CSV-Import oder UI. Wenn diese Grenze benannt ist, kann Claude Code konkrete Regeln umsetzen: Validierungsfehler geben 400 zurueck, temporaere externe Fehler duerfen wiederholt werden, und Batch-Fehler werden so gespeichert, dass man sie sicher erneut ausfuehren kann.

Dieser Artikel ist bewusst einsteigerfreundlich, aber produktionsnah. Er enthaelt ein kopierbares TypeScript-Beispiel, drei konkrete Use Cases, typische Fallen, einen Review-Prompt fuer Claude Code, offizielle Referenzen und eine CTA fuer Training oder wiederverwendbare Materialien.

Erst Wiederherstellung, dann Klassennamen

Ob der Typ AppError, DomainError oder HttpError heisst, ist zweitrangig. Wichtiger ist die Frage: Was soll das System als Naechstes tun?

GrenzeBeispielAntwortWiederherstellung
API-ValidierungFalsche E-Mail, Zahl ausserhalb des Bereichs, kaputtes JSON400Nutzer korrigiert die Eingabe
Externe APIPayment, CRM, E-Mail oder Analytics nicht verfuegbar502 oder 503Retry, Pause, temporaeren Fehler melden
Job/BatchNachtbericht, CSV-Import, BenachrichtigungInterner FehlerdatensatzSicherer Retry, Dead-Letter-Queue, Alert

Ein lesbarer message reicht nicht aus. Menschen koennen ihn lesen, aber Code kann daraus schlecht entscheiden. Felder wie kind, code, retryable und status machen Verhalten pruefbar. Genau das hilft Claude Code, weil es nicht anhand freier Texte raten muss.

Ausfuehrbares TypeScript-Beispiel

Das folgende Beispiel laeuft mit Node.js 18 oder neuer. Es nutzt tsx, um TypeScript direkt auszufuehren, und ruft keine echte externe API auf. Der fetcher wird injiziert, damit der Fehler stabil reproduzierbar ist.

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: API-Validierung

Validierungsfehler sind meist durch den Nutzer korrigierbar. Eine falsche E-Mail, ein zu niedriges Alter, ein Body ohne Objektform oder ein unbekannter Plan sollten nicht wie ein Serverabsturz aussehen. Im Beispiel klassifiziert parseUser den Fehler als validation, gibt 400 zurueck und setzt retryable: false.

Das hilft Frontend, Support und Betrieb. Das UI kann das richtige Feld markieren, Logs lassen sich nach EMAIL_INVALID filtern, und Claude Code kann Tests fuer Fehlerpfade ergaenzen. Wenn du daraus eine Teststrategie machen willst, lies auch API-Tests mit Claude Code und Claude Code Testing Strategies.

Use Case 2: Externe API-Fehler

Externe Dienste fallen aus, auch wenn dein Code korrekt ist. Payment, E-Mail, CRM, Tabellen und Analytics koennen Timeouts, Rate Limits oder unerwartete Payloads liefern. Entscheidend ist die Trennung zwischen retryable und non-retryable.

Im Beispiel wird ein 5xx als retryable: true markiert, aber eine falsche Payload-Form als retryable: false. Eine kaputte Antwort immer wieder zu versuchen, erzeugt nur Queue- und Log-Laerm. Fuer HTTP-Semantik ist MDN Response.ok die passende Referenz. Bei Express-Projekten gehoert Express error handling ebenfalls in die Review-Checkliste.

Use Case 3: Job- und Batch-Fehler

Jobs scheitern oft, wenn niemand auf eine Seite schaut. Nachtberichte, CSV-Importe, Rechnungen und Benachrichtigungen brauchen deshalb wiederholbare Spuren. runJob speichert Jobnamen, letzte Versuchszahl und Retrybarkeit. In Produktion sollte das in strukturierte Logs, eine Dead-Letter-Queue, ein Admin-UI oder einen Alert fliessen.

Der wichtigste Begriff ist Idempotenz. Eine idempotente Operation kann erneut ausgefuehrt werden, ohne zusaetzliche Nebenwirkungen zu erzeugen. Wenn ein CSV-Import doppelte Zeilen anlegt oder ein Billing-Job doppelt abbucht, ist Retry-Logik selbst ein Risiko. Claude Code sollte deshalb Wiederholbarkeit und Seiteneffekte pruefen, nicht nur die Syntax.

Typische Fallen

Die erste Falle ist catch { return null; }. Damit verschwindet der Beweis, den Claude Code und Menschen zum Debuggen brauchen. Die zweite Falle ist das Leaken interner Details: Stack Traces, SQL-Namen, Umgebungsvariablen oder Token-Fragmente gehoeren nicht in Nutzerantworten. Fuer die Sicherheitsseite siehe Claude Code Security Audit. Die dritte Falle ist, alles zu wiederholen. Validierungsfehler und falsche Payloads werden durch Warten nicht besser.

Eine vierte Falle ist, Typen einzufuehren, aber keine Teamregel zu hinterlassen. TypeScript Narrowing und discriminated unions sind stark, doch morgen kann wieder jemand throw new Error("failed") schreiben. Nutze die offizielle Doku zu TypeScript Narrowing und dokumentiere die Regel in AGENTS.md oder CLAUDE.md.

Review-Prompt fuer Claude Code

Bitte pruefe das Error Handling in diesem PR.
Checkliste:
1. Fehler werden an API-, externer-API- und Job/Batch-Grenzen klassifiziert.
2. Nutzerkorrigierbare Fehler werden nicht als 500 zurueckgegeben.
3. retryable und non-retryable sind getrennt.
4. Antworten leaken keine Stack Traces, SQL-Namen, Secrets oder internen Pfade.
5. Logs enthalten code, kind, attempt und sichere cause-Information.
6. Es gibt mindestens 3 Tests fuer Fehlerpfade.
Gib den kleinsten sicheren Patch und die passenden Tests aus.

Zum Fixieren von Fehlerpfaden reicht oft der Node.js test runner. Claude-Code-Einstellungen und Projekt-Memory pruefst du ueber Claude Code overview. Fuer testgetriebene Aenderungen passen TDD mit Claude Code und Debugging-Techniken.

CTA und Masas Ergebnis

Error Handling eignet sich sehr gut fuer Teamtraining, weil API, Logs, Sicherheit, Tests und Betrieb zusammenkommen. Zum Einstieg gibt es die kostenlose Cheat Sheet. Fuer Prompts, Review-Checklisten und Templates lohnt sich die Produktbibliothek. Wenn ein bestehendes Repository auf Claude-Code-faehige Regeln gebracht werden soll, hilft die Seite Claude Code Training und Beratung.

In Masas Workflow wurden Prompts deutlich kuerzer, nachdem Validierung, externe APIs und Batch-Fehler in eine aehnliche AppError-Form gebracht wurden. Statt “repariere diesen Fehler sauber” kann die Anweisung lauten: validation gibt 400 zurueck, external nutzt retryable, job speichert attempt. Die Review konzentriert sich auf Antwort, Log und Test. Das ist keine Magie, aber viel besser betreibbar als anonyme 500 ueberall.

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

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.