- Published on
Claude-API: Fehler behandeln statt pauschal abfangen
- Authors

- Name
- Phillip Pham
- @ddppham
Fehlerbehandlung bei der Claude-API
TL;DR
Das SDK wiederholt Verbindungsfehler, 408, 409, 429 und alles ab 500 automatisch — zweimal, mit steigendem Abstand. Was Sie selbst behandeln müssen, ist die Unterscheidung zwischen wiederholbar und aussichtslos. Ein pauschales except wirft genau diese Information weg.
Die Fehlerübersicht
| Code | Typ | Wiederholbar | Häufige Ursache |
|---|---|---|---|
| 400 | invalid_request_error | nein | Ungültige Anfrage oder Parameter |
| 401 | authentication_error | nein | Schlüssel fehlt oder ist ungültig |
| 403 | permission_error | nein | Fehlende Berechtigung |
| 404 | not_found_error | nein | Falsche Modell-ID oder Endpunkt |
| 413 | request_too_large | nein | Anfrage über der Größengrenze |
| 429 | rate_limit_error | ja | Kontingent überschritten |
| 500 | api_error | ja | Serverseitiges Problem |
| 529 | overloaded_error | ja | Dienst vorübergehend überlastet |
Die Kette statt des Sammelfangs
Ordnen Sie von der spezifischsten Klasse zur allgemeinsten und behandeln Sie jede Kategorie unterschiedlich:
import anthropic
try:
antwort = client.messages.create(...)
except anthropic.NotFoundError:
# 404 — falsche Modell-ID. Wiederholung sinnlos.
log.error("Modell-ID prüfen")
raise
except anthropic.RateLimitError as e:
# 429 — der Kopf sagt, wie lange zu warten ist
wartezeit = int(e.response.headers.get("retry-after", "60"))
time.sleep(wartezeit)
except anthropic.APIStatusError as e:
# jede andere Antwort außerhalb 2xx
if e.status_code >= 500:
wiederholen() # 500, 529 — vorübergehend
else:
log.error(f"{e.status_code}: {e.message}")
raise # 4xx — die Anfrage stimmt nicht
except anthropic.APIConnectionError:
# Netzfehler, bevor eine Antwort kam
wiederholen()
In Python ist APIConnectionError ein Geschwister von APIStatusError; in TypeScript ist es eine Unterklasse von APIError und muss deshalb vor ihr geprüft werden. In Go gibt es eine einzige Fehlerklasse — dort packen Sie mit errors.As aus und verzweigen über StatusCode.
Für feinere Unterscheidungen als der Statuscode gibt es .type: Damit trennen Sie etwa einen Abrechnungsfehler von einer fehlenden Berechtigung, die beide als 403 kommen.
Die Modell-400er
Ein Fehler 400 heißt normalerweise "die Anfrage ist falsch gebaut". Bei neueren Modellen heißt er häufiger "dieser Parameter existiert nicht mehr". Die Fälle, die bei einer Migration systematisch auftreten:
| Parameter | Auf welchen Modellen 400 |
|---|---|
temperature, top_p, top_k | Claude Opus 5, Fable 5, Opus 4.8, Opus 4.7 |
thinking: {type: "enabled", budget_tokens: N} | dieselben — ersetzt durch {"type": "adaptive"} |
| Vorbelegung der letzten Assistenten-Nachricht | Claude Opus 5, Fable 5, die 4.6er-Familie |
thinking: {type: "disabled"} mit effort xhigh/max | Claude Opus 5 |
thinking: {type: "disabled"} überhaupt | Claude Fable 5 |
Und der unangenehmste, weil er nicht nach einem Anfrageproblem aussieht: Bei Claude Fable 5 scheitert jede Anfrage mit 400, wenn die Datenaufbewahrung Ihrer Organisation unter 30 Tagen liegt — auch bei vollkommen gültigem Anfragekörper. Wenn ein Modell durchgängig mit 400 antwortet und andere funktionieren, prüfen Sie die Organisationskonfiguration, bevor Sie den Prompt debuggen. Details im Beitrag zur Datenaufbewahrung.
Die Zeitüberschreitungsfalle
Zwei Dinge, die regelmäßig überraschen.
Die Einheit unterscheidet sich je SDK. Python und Ruby erwarten Sekunden, TypeScript Millisekunden. Ein aus Python übernommenes timeout: 30 bedeutet in TypeScript 30 Millisekunden — und dann scheitert alles, ohne dass die Ursache offensichtlich wäre.
Zeitüberschreitungen werden wiederholt. Die tatsächliche Wanduhrzeit kann deshalb timeout × (max_retries + 1) erreichen. Bei der Voreinstellung von 10 Minuten und zwei Wiederholungen sind das bis zu 30 Minuten für einen Aufruf, den Sie für begrenzt hielten.
Wenn Sie eine harte Obergrenze brauchen, setzen Sie beides:
client.with_options(timeout=30.0, max_retries=1).messages.create(...)
Was das SDK schon tut
Bevor Sie eigene Wiederholungslogik bauen: Das SDK wiederholt Verbindungsfehler, 408, 409, 429 und alles ab 500 selbstständig mit steigendem Abstand — voreingestellt zweimal. max_retries=0 schaltet es ab.
Eigene Logik lohnt sich nur, wenn Sie darüber hinaus etwas brauchen: eine Obergrenze über den gesamten Vorgang, ein Ausweichen auf ein anderes Modell, oder eine Sicherung gegen dauerhafte Überlastung.
Zwei Fehlerbilder, die keine sind
stop_reason: "refusal" kommt als HTTP 200 mit leerem Inhalt. Kein Ausnahmefehler, kein Statuscode — Code, der ungeprüft auf content[0] zugreift, bricht trotzdem. Die Behandlung steht im Beitrag zu Ablehnungen.
stop_reason: "max_tokens" ist ebenfalls eine erfolgreiche Antwort — nur abgeschnitten. Prüfen Sie stop_reason grundsätzlich, bevor Sie eine Antwort weiterverarbeiten.
Und stop_details ist nur bei einer Ablehnung befüllt; bei allen anderen Abbruchgründen ist es null. Wer ungeprüft darauf zugreift, produziert einen Fehler in der Fehlerbehandlung.
Häufig gestellte Fragen
Wiederholt das Anthropic-SDK Fehler automatisch?
Ja — Verbindungsfehler, 408, 409, 429 und alles ab 500 werden mit steigendem Abstand wiederholt, voreingestellt zweimal. Eigene Wiederholungslogik brauchen Sie nur für darüber hinausgehende Anforderungen wie eine Gesamtobergrenze oder ein Ausweichen auf ein anderes Modell.
Welche Fehler sollte ich nicht wiederholen?
Alle 4xx außer 429: 400 bedeutet eine ungültige Anfrage, 401 einen ungültigen Schlüssel, 403 eine fehlende Berechtigung, 404 eine falsche Modell-ID, 413 eine zu große Anfrage. Eine Wiederholung ändert daran nichts und verbraucht nur Zeit und Kontingent.
Warum scheitern alle Anfragen an einem Modell mit Fehler 400?
Wenn andere Modelle funktionieren, liegt es meist nicht am Anfragekörper. Häufigste Ursachen: ein Parameter, den das neuere Modell nicht mehr kennt — temperature, top_p, top_k oder budget_tokens —, oder bei Claude Fable 5 eine Datenaufbewahrung unter 30 Tagen in der Organisationskonfiguration.
Wie lange kann ein Aufruf tatsächlich dauern?
Bis zu timeout × (max_retries + 1), weil Zeitüberschreitungen wiederholt werden. Bei der Voreinstellung von zehn Minuten und zwei Wiederholungen sind das bis zu 30 Minuten. Für eine harte Obergrenze setzen Sie beide Werte gemeinsam herab.
Warum funktioniert mein Timeout in TypeScript nicht?
Weil die Einheit sich unterscheidet: Python und Ruby erwarten Sekunden, TypeScript Millisekunden. Ein aus einem Python-Beispiel übernommenes timeout: 30 bedeutet in TypeScript 30 Millisekunden, und dann scheitert praktisch jeder Aufruf — mit einer Fehlermeldung, die nicht auf die Ursache zeigt.
Der nächste Schritt
Suchen Sie in Ihrem Code nach einem einzelnen pauschalen except um den Modellaufruf. Ersetzen Sie es durch eine Kette, die mindestens zwischen 429, ab 500 und 4xx unterscheidet — das ist eine halbe Stunde Arbeit und beendet den größten Teil unnötiger Wiederholungen. Wir schauen gern mit drauf.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
Claude-Modell wechseln: die Fehler-400-Liste vorab
Vier Parameter, die auf neueren Modellen einen Fehler 400 geben, plus zwei stille Änderungen, die keinen Fehler werfen und trotzdem etwas kaputtmachen.
Wenn Claude ablehnt: HTTP 200 und leerer Inhalt
Eine abgelehnte Anfrage kommt als erfolgreiche Antwort mit leerem Inhalt. Code, der auf content[0] zugreift, bricht dabei.
Claude-Antworten strömen: ab wann es Pflicht wird
Ab etwa 16.000 Ausgabe-Token laufen nicht-gestromte Anfragen in Zeitüberschreitungen. Der Umbau kostet drei Zeilen — und löst nebenbei ein Latenzproblem.
Bereit für KI im Mittelstand?
Nutzen Sie unsere 10 kostenlosen KI-Tools und Praxis-Guides – oder sprechen Sie direkt mit unseren Experten.
Pexon Consulting – KI-Beratung für den Mittelstand | Scaly Academy – Geförderte KI-Weiterbildung (KI-Spezialist, KI-Experte, Workflow-Automatisierung)