Errors

HTTP-Status-Codes, Body-Format und Retry-Strategie - was die go~mus API im Fehlerfall zurückgibt und wie du darauf sauber reagierst.

Die go~mus API antwortet bei Fehlern mit einem passenden HTTP-Status und einem JSON-Body in einem von zwei Schemata. Diese Seite zeigt, welche Codes in der Praxis auftreten, wie der Body aussieht, und wie du pro Fehlerklasse reagieren sollten.

Status-Codes im Überblick

CodeWannRetry sinnvoll?
200 / 201Erfolg-
202 AcceptedAsynchroner Prozess läuft (z.B. Dokument-Virenscan), Ergebnis später abholenJa, nach kurzem Backoff
401 UnauthorizedToken fehlt, abgelaufen oder ungültigNein, Token tauschen
403 ForbiddenToken gültig, aber Permission fehltNein, mit anderem User/Permission probieren
404 Not FoundResource existiert nicht, oder Route ungültigNein, ID prüfen
410 GoneResource war da, ist nicht mehr verfügbar (z.B. abgelaufenes Dokument)Nein
422 Unprocessable EntityValidierungs- oder Business-Logic-Fehler (häufigster Fehlerfall)Bedingt - nur wenn die Ursache transient ist (siehe unten)
5xxServerseitiger FehlerMit exponential Backoff bis 3-5 Versuche

429 Rate-Limit haben wir derzeit nicht aktiv im Einsatz. Wenn du API-Calls bündeln, planst du trotzdem moderate Concurrency ein.

Body-Format

Zwei Varianten, je nach Endpoint:

Einfacher Fehler

{
  "error": "reservation not valid anymore"
}

Das ist die häufigste Form - vor allem bei 422 und 401. Eine kurze, menschenlesbare Botschaft, kein Maschinen-Code, keine Locale-Negotiation. dein solltet die Botschaft loggen, aber für End-User-Anzeige eigene Texte mappen.

Fehler mit Feldliste

{
  "error": "customer could not be saved",
  "errors": [
    "Email can't be blank",
    "Phone is too short (minimum is 5 characters)"
  ]
}

Bei Validierungs-Fehlern auf nested Objekten (Customers, Orders, Requests, Contacts) kommt zusätzlich ein errors-Array mit Feld-Validierungen. Die Strings sind nicht maschinenlesbar - sie sind direkt aus der ActiveRecord-Validierung. Für End-User-Anzeige deine eigenen Texte.

Fehlerklassen mit Beispielen

401 - Token-Probleme

{ "error": "authentication error; no customer or no user present" }

Häufige Ursachen:

  • Authorization-Header fehlt komplett
  • Bearer-Token tippfehler oder abgelaufen
  • Token aus einer anderen Instance benutzt (Tokens sind instance-scoped)

Reaktion: nicht retryen, frisches Token holen. Hilfreich beim Debuggen: die letzten 4 Zeichen des verwendeten Tokens loggen, dann siehst du im Vergleich, welcher Token gerade aktiv war.

422 - Validierung und Business-Logic

{ "error": "reservation is invalid: ticket is required, quantity must be > 0" }

oder

{ "error": "reservation not possible" }

Die typischen Fälle:

  • Pflichtfelder fehlen im POST/PUT-Body
  • Werte außerhalb des erlaubten Bereichs (Datum in der Vergangenheit, Quantity > Capacity)
  • State-Konflikte: Reservation abgelaufen, Slot inzwischen ausgebucht, Order schon finalisiert
  • Konfigurations-Konflikte: Ticket nicht im aktuellen Auth-Kontext buchbar, Tour ohne passende Sprache

Reaktion hängt vom Sub-Fall ab:

  • Pflichtfelder fehlen → Frontend-Validierung nachbessern, kein Retry
  • Slot ausgebucht → Verfügbarkeit neu abfragen, User um Auswahl bitten, kein blinder Retry
  • Reservation abgelaufen → neue Reservation anlegen
  • Race-Condition (zwei parallele Order-Creates auf denselben Slot) → mit kleiner Verzögerung einmal retryen, dann aufgeben

404 - Resource fehlt

{ "error": "invalid route" }

oder

{ "error": "customer not found" }

Klassiker:

  • Numerische ID, die es nicht gibt (oder die archiviert wurde)
  • Token in URL, der nie existierte oder schon weg ist (reservation_token)
  • Tippfehler in der Route

Reaktion: nicht retryen. Auf der UI passend "nicht gefunden" anzeigen.

410 - Resource ist weg

Selten, aber bei documents/:id/download (siehe Documents-Endpoint) und ähnlichen kommt es vor: das Dokument ist auf dem Server gewesen, ist aber inzwischen außer Reichweite (z.B. Aufbewahrungsfrist überschritten). Reaktion: nicht retryen, dem User sagen "nicht mehr verfügbar".

5xx - Serverseitiger Fehler

Wenn die go~mus-Instance kurz nicht antwortet (Deployment, Datenbank-Hick), erhältst du 502/503/504. Reaktion: exponential Backoff, 3-5 Versuche, danach Error-State im UI. Bei nicht-idempotenten Calls (POST Order, POST Reservation) Vorsicht beim Retry - der Server kann den Call schon empfangen und verarbeitet haben.

Idempotenz und Retry

Eine Faustregel:

HTTP-MethodeRetry-sicher?
GET, HEAD, OPTIONSJa
PUT, DELETEJa
POSTNein, ohne extra Schutz

Das heißt für POST /orders, POST /reservations, POST /requests:

  • Auf Client-Seite den Erfolg eindeutig erkennen: 200/201 mit gültigem Response-Body, sonst nicht erneut absenden.
  • Bei Timeout vor Retry erst prüfen: Bei Order und Request gibt es Listen-Endpoints (GET /orders, GET /requests), in denen der Eintrag zu finden ist, falls der Server ihn doch angelegt hat. Bei Reservation gibt es kein Lookup - im Zweifel den vorherigen Token verfallen lassen und neu anlegen.
  • Foreign IDs nutzen: Wenn du Customers oder Orders mit deinem eigenen System synchronisieren, nutzt du foreign_id als externen Schlüssel - dann kann der Server bei Wiederholungen den Duplikat erkennen, oder du in deinem System.

Mehr dazu in Best Practices.

Was du loggst sollten

Pro fehlgeschlagenem Call mindestens:

  • HTTP-Status, vollständiger URL-Pfad mit Query-Params (Token-Werte maskiert)
  • Body-Auszug aus dem Response (error und errors-Array)
  • Zeitstempel (UTC) und Korrelations-ID, falls du eine setzen
  • Letzte 4 Zeichen des verwendeten Bearer-Tokens (zur Identifikation, ohne Secret zu exponieren)

Das macht dir und uns das Debugging im Support-Fall um Größenordnungen einfacher.

Verwandte Seiten