Fehlerbehandlung und Statuscodes
1) Warum Fehler standardisieren
Ein einziger Fehlervertrag beschleunigt das Debugging von Clients, reduziert falsche Retrays und macht RCA reproduzierbar. Gutes System:- vorhersehbar kodiert die Art des Problems,
- gibt dem Kunden gültige Hinweise (was als nächstes zu tun ist),
- schützt vor undichten Innenteilen,
- kompatibel mit Retrays und Idempotenz.
2) Gestaltungsprinzipien
1. Ein Fehlerschema für alle Dienste (REST/GraphQL/gRPC/Webhooks).
2. Klare Semantik der Retrays: Welche Codes retratieren, welche nicht.
3. Fail-closed bei Write-Operationen: besser 4xx/5xx als stille Unkonsistenz.
4. Keine Lecks: SQL, Stacks, Configs, interne IDs nicht offenlegen.
5. Trace: Geben Sie immer 'trace _ id '/' correlation _ id' zurück.
6. Die Lokalisierung der Nachrichten ist optional, aber die Codes und der 'Grund' bleiben stabil.
3) Einheitliches Format (Problemdetails/JSON)
Empfohlenes Grundformat (kompatibel mit RFC 7807):json
{
"type": "https://errors.example.com/auth/invalid-token",
"title": "Invalid access token",
"status": 401,
"code": "AUTH_INVALID_TOKEN",
"detail": "Token expired or signature invalid.",
"instance": "/api/v1/payments/12345",
"trace_id": "01HX3...ABC",
"hint": "Obtain a new token via OAuth2 refresh.",
"meta": {
"scope": "payments:write",
"policy": "deny-by-default"
}
}
Erläuterungen:
- 'type' ist die stabile URL-ID der Fehlerklasse.
- 'code' ist der kurze Maschinencode der Domain (stabil zwischen Releases).
- 'hint' - was der Client tun soll (wiederholen, Token aktualisieren, Parameter ändern).
- 'meta' - sichere Teile (ohne Geheimnisse und PII).
4) Statuscode-Karte (Mindestsatz)
Authentifizierung/Autorisierung
400 Bad Request - strukturelle Validierung/Schema.
401 Unauthorized - kein/nicht validierter Token. 'WWW-Authenticate' hinzufügen.
403 Forbidden - authentifiziert, aber keine Rechte/Richtlinien verweigert.
404 Not Found - Maskieren Sie die Existenz der Ressource, wenn keine Rechte vorhanden sind.
409 Conflict - Versions-/Zustandskonflikt (optimistische Sperre, Idempotenz).
451 Unavailable For Legal Reasons - Einheit für Compliance/Gerichtsbarkeit.
Grenzen und Schutz
408 Request Timeout - Client sendet Körper zu langsam.
409/425 Too Early - Verbot der frühen Wiederholung in 0-RTT/TLS 1. 3.
429 Too Many Requests - mit 'Retry-After' und Limitpolitik.
499 Client Closed Request - (am Perimeter/NGINX) Der Client hat die Verbindung getrennt.
Daten und Geschäftsregeln
422 Unprocessable Content - Die geschäftliche Validierung hat das Schema bestanden, aber die Bedeutung ist falsch.
423 Gesperrt - Ressource gesperrt (KYC-Überprüfung, AML-Freeze).
409 Conflict - Double Send, Race, State Limit (z.B. „bereits in Bearbeitung“).
410 Gone - Endpunkt/Ressource entfernt (Deprecate abgeschlossen).
Serverräume
500 Interner Serverfehler - unbekannter Fehler; Details nicht preisgeben.
502 Bad Gateway - Abhängigkeit hat Fehler/Proxy zurückgegeben.
503 Service Unavailable - Degradation/geplante Arbeiten; „Retry-After“ wird hinzugefügt.
504 Gateway Timeout - Zeitüberschreitung von Abhängigkeiten.
Regel: write-Operationen im Zweifel → 409 (Konflikt) oder 503 (Wiederholung später), nicht 200.
5) Semantik von Retrays und Idempotenz
Kann nicht zurückgezogen werden: 400/ 401/403/404/422 (wenn der Kunde die Anfrage nicht geändert hat).
Sie können zurückziehen: 408/429/5xx/ 425/499/504 (mit backoff + jitter).
Idempotenz: Für 'POST' den 'Idempotency-Key' (UUIDv4) einschalten.
Geben Sie 409 mit 'hint: „Use same Idempotency-Key or GET status“ (Gleiche Identität-Schlüssel oder GET-Status verwenden) zurück, um den Konflikt erneut auszuführen.
Fügen Sie' Idempotency-Replay: true' hinzu, wenn Sie das gespeicherte Ergebnis zurückgeben.
HTTP/1.1 429 Too Many Requests
Retry-After: 3
RateLimit-Limit: 50
RateLimit-Remaining: 0
RateLimit-Reset: 1730641030
6) Eingangsvalidierung: Feldfehlerstruktur
Verwenden Sie für 400/422 eine Reihe von Feldfehlern:json
{
"type": "https://errors.example.com/validation",
"title": "Validation failed",
"status": 422,
"code": "VALIDATION_ERROR",
"trace_id": "01HX4...XYZ",
"errors": [
{"field": "amount", "rule": "min", "message": "Must be >= 10"},
{"field": "currency", "rule": "enum", "message": "Unsupported currency"}
]
}
7) Teilausfälle (Batch/Teilausfall)
In Batch-Endpoints verstecken Sie keine Fehler innerhalb von 200 ohne Struktur. Geben Sie 207 Multi-Status oder 200 c mit einem Array von Ergebnissen zurück, wobei jeder Job einen anderen Status hat:json
{
"status": "partial",
"succeeded": 8,
"failed": 2,
"results": [
{"id": "op1", "status": 201},
{"id": "op2", "status": 422, "error": {"code":"VALIDATION_ERROR","detail":"..."}}
]
}
8) Pagination und „leere“ Antworten
Leere Sammlung - 200 mit 'items: []', nicht 404.
Das Ende der Seite ist 'next _ page _ token' fehlt.
Der falsche Token ist 400 mit 'code: PAGINATION_CURSOR_INVALID'.
9) Webhooks: zuverlässige Lieferung
Signieren Sie Ereignisse (HMAC) und überprüfen Sie vor der Verarbeitung.
Die Antwort auf eine erfolgreiche Verarbeitung ist 2xx (besser 204).
Temporäre Ausfälle des Empfängers - 5xx; Absender wiederholt (exponentieller Backoff, Jitter).
Deduplizierung durch 'event _ id' und Speicherung des Ergebnisses (idempotent consumer).
Ungültige payload - 400/422 ohne Wiederholungen.
10) Konformität mit Protokollen (gRPC/GraphQL)
gRPC → HTTP:- `INVALID_ARGUMENT` → 400
- `UNAUTHENTICATED` → 401
- `PERMISSION_DENIED` → 403
- `NOT_FOUND` → 404
- `ALREADY_EXISTS` → 409
- `FAILED_PRECONDITION` → 412/422
- `RESOURCE_EXHAUSTED` → 429
- `ABORTED` → 409
- `UNAVAILABLE` → 503
- `DEADLINE_EXCEEDED` → 504
json
{
"data": { "createPayment": null },
"errors": [{
"message": "Forbidden",
"extensions": { "code": "FORBIDDEN", "status": 403, "trace_id": "..." },
"path": ["createPayment"]
}]
}
Es wird empfohlen, bei kritischen Fehlern nicht 200, sondern den entsprechenden HTTP-Code zu verwenden.
11) Überschriften und Kundenhinweise
„Retry-After“ - Sekunden/NTTR-Datum (429/503/425/408).
„Warning“ - weiche Degradationen oder Deprecate („199 - Feature X ist deprecated“).
`Deprecation`, `Sunset`, `Link: <...>; rel = „deprecation“'- für kontrollierte Abschaltung.
'Problem-Type' (custom) - schnelle Routing von Fehlern auf dem Client.
'X-Trace-Id '/' Correlation-Id' - Verknüpft Protokolle/Traces.
12) Nachrichtensicherheit
Wiederholen Sie keine Eingabegeheimnisse (Token/Signaturen) im Antworttext.
PAN/PII maskieren ('1234').
Für 401/403 - Legen Sie nicht offen, welches Attribut genau fehlgeschlagen ist.
Für 404 statt „resource exists but not yours“ - eben 404.
13) Fehlerbeobachtbarkeit
Metriken:- `http_errors_total{status, route, tenant}`
- 'error _ classes _ total {code}' (durch 'code' vom Körper)
- Anteil 429, 5xx; „p95 “/„ p99“ Latenz für fehlerhafte Antworten separat
- 'retry _ after _ seconds _ bucket' - Histogramm der Wiederholungstipps
- Verknüpfen Sie die Antwort mit 'trace _ id', speichern Sie' code', 'type', 'status', 'route', 'tenant', ohne PII.
- Spritzer '5xx _ rate> X%' bei RPS> N;
- Wachstum von 429 auf kritischen Strecken;
- „timeout/504“ für Abhängigkeiten;
- häufige 409/idempotency → ein Zeichen von Rennen.
14) Beispiele
14. 1.422 (geschäftliche Validierung)
json
{
"type": "https://errors.example.com/payments/limit-exceeded",
"title": "Limit exceeded",
"status": 422,
"code": "PAYMENT_LIMIT_EXCEEDED",
"detail": "Daily withdrawal limit reached for KYC1.",
"hint": "Increase limits after KYC2 or try tomorrow.",
"trace_id": "01J5...XYZ"
}
14. 2.409 (Idempotenz)
HTTP/1.1 409 Conflict
Idempotency-Replay: true
json
{
"type": "https://errors.example.com/idempotency/replay",
"title": "Duplicate request",
"status": 409,
"code": "IDEMPOTENT_REPLAY",
"detail": "A request with the same Idempotency-Key was already processed.",
"hint": "Reuse the same Idempotency-Key and GET the operation status."
}
14. 3.429 (Grenzen)
json
{
"type":"https://errors.example.com/rate/too-many-requests",
"title":"Too many requests",
"status":429,
"code":"RATE_LIMITED",
"detail":"Per-key rate limit exceeded.",
"hint":"Retry after the time specified in Retry-After header."
}
15) Antipatterns
Gibt 200 mit Fehlertext im Körper zurück.
Mischen Sie verschiedene Fehlerformate zwischen den Diensten.
Stack/SQL/Tabellennamen/interne URLs im 'Detail' offenlegen.
Verwenden Sie' message' anstelle von stable' code '/' type'.
Geben Sie 500 zurück, wenn ein Geschäftsfehler erwartet wird (z. B. „Saldo nicht ausreichend“).
Inkonsistente Semantik zwischen REST/GraphQL/gRPC.
16) Spezifität von iGaming/Finanzen
Eindeutige Codes für KYC/AML/Sanktionen: „KYC _ REQUIRED“, „KYC _ REVIEW“, „AML _ LOCK“, „SANCTION _ BLOCKED“.
Einschränkungen der Gerichtsbarkeiten: 451 mit sicherer Formulierung ohne Angabe von Listen.
Geldschreibvorgänge: 409/423 bei Konkurrenz und Sperren, 'hint' mit Wiederholungsfenster.
Spieler-Limits-Invarianten: Verwenden Sie 422 für Verstöße gegen verantwortungsvolle Zahlungsregeln.
Audit: Unveränderliche Entscheidungsprotokolle (Code, Zeit, Akteur, trace_id).
17) Checkliste Prod-Ready
- Einheitliches JSON-Fehlerschema, stabile' type '/' code'.
- HTTP ↔ gRPC/GraphQL Mupping vereinbart und dokumentiert.
- Retraysemantik + 'Retry-After'; Idempotenz für Schreiben.
- Maskierung von PII/Geheimnissen; 404, um Ressourcen zu verbergen.
- Fehlermetriken und Warnungen; Korrelation mit 'trace _ id'.
- Deprecate policies: 'Deprecation', 'Sunset', 'Link'.
- Tests: negativ/fuzz, Versionskonflikt, fallende Abhängigkeiten, double-submit.
- Hyde Kunden: Beispiele für Backoffs und 409/422/429/5xx Verarbeitung.
18) TL; DR
Standardisieren Sie das einheitliche JSON-Fehlerformat c 'type '/' code '/' trace _ id', verwenden Sie korrekte HTTP-Codes, unterscheiden Sie zwischen Validierung (400/422), (401/403/404), Konflikten/Idempotenz (409) und Limits (429). Geben Sie klare' Retry-After 'und' hint', maskieren Sie sensible Daten, protokollieren Sie Fehler mit 'trace _ id' und erstellen Sie Alerts unter 5xx/429/p99.