maesn
Produkt-Feature

Unified Error Handling macht aus jedem Fehler eine vorhersehbare Form

Rohe APIs sind sich uneins, wo ein Fehler steht, wie er heißt und ob sich ein Retry lohnt. Maesn liefert einen Umschlag mit standardisierter Kategorie, fängt ungültige Eingaben ab, bevor sie gesendet werden, und reicht den Fehler des Zielsystems unverändert durch.

Drei Fehlerdialekteein Umschlag
System A{ "Message": "…" }
System B{ "fault": { "code": 12 } }
System CHTTP 200, Fehler im Rumpf
maesn kategorisiert ihn
Immer diese Form
"errors": {
  "type": "target_system_error",
  "statusCode": 400,
  "downstreamErrors": [{
    "statusCode": 500,
    "message": "Unknown currency"
  }]
}
Das System antwortete mit 500 auf einen Währungscode, den es nicht gibt. Der Fall scheitert jedes Mal gleich, deshalb trägt der Umschlag die 400, die ihm zusteht, und die Antwort des Systems reist mit.
Diese Software-Teams vertrauen uns
HubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinHEROHolviLanes & PlanesAgicapHubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinHEROHolviLanes & PlanesAgicap
Das Konzept

Was ist Unified Error Handling

Anbindungen werden danach beurteilt, wie sie sich verhalten, wenn etwas schiefgeht, nicht wenn alles läuft. Der Normalfall ist die leichte Hälfte: Sie bauen ihn an einem Nachmittag gegen ein System. Die andere Hälfte ist, um drei Uhr nachts zu wissen, ob ein gescheiterter Abgleich eine fehlerhafte Nutzlast bedeutet, einen Kunden, der den Zugriff entzogen hat, einen Endpunkt, den es für dieses System nie gab, oder einen Hersteller mit einer schlechten Stunde, und welches davon einen zweiten Versuch wert ist.

Unified Error Handling ist die Ebene, die das beantwortbar macht. Ein Umschlag, eine standardisierte Menge von Kategorien und eine dokumentierte Retry-Regel, über jedes System hinweg, Ihre Fehlerbehandlung wird also einmal geschrieben. Sie stützt sich auf dieselbe Normalisierung wie das Common Data Model: Weil Maesn weiß, wie ein gültiges Objekt aussieht, kann es ein fehlerhaftes abweisen, bevor ein System es sieht.

Das Problem

Jedes System scheitert in seinem eigenen Dialekt

Scheitern ist das am wenigsten standardisierte Verhalten jeder API und das, dem Sie unter dem größten Druck begegnen. Vier Fragen, vier verschiedene Antworten je System.

Wo der Fehler steckt
Statuscodeim Rumpfin einem fault
Wie er heißt
messageMessagefault.code
Liegt es an Ihnen
unklar400 für beideskeine Kategorie
Sollten Sie wiederholen
undokumentiertratennochmal versuchen
Wie Maesn damit umgeht

Ein Umschlag, sechs nützliche Felder

Fehler kommen in einem einzigen Objekt auf oberster Ebene an, jedes Mal mit denselben Feldern. Zwei davon sind der Grund, warum das mehr ist als kosmetische Normalisierung.

Jeder Fehler, ein Umschlag
typeDie standardisierte Kategorie, damit Sie auf die Fehlerart verzweigen statt Prosa zu parsen.
statusCodeDer normale HTTP-Code, passend zur Kategorie, sodass beide sich nie widersprechen.
messageEine kurze Erklärung des Fehlers, gedacht für einen Menschen im Log, nicht zum Parsen.
contextWelches Zielsystem, welche Unified API und der Zeitstempel, damit Sie die Anfrage finden.
validationErrorsWas Maesn vor dem Senden abgewiesen hat, Feld für Feld, wenn Ihre Eingabe das Schema verfehlt.
downstreamErrorsWas das Zielsystem selbst gemeldet hat, wörtlich durchgereicht.

Eine Kategorie, kein Satz

Jeder Fehler trägt einen standardisierten type, sodass Ihr Code auf die Fehlerart verzweigt statt Strings zu vergleichen.

Gefangen vor dem Senden

Maesn prüft zuerst Feldformate, Pflichtwerte und Datentypen, sodass ungültige Eingaben früh scheitern und das Feld benannt wird.

Downstream-Fehler erhalten

Weist ein Zielsystem eine Anfrage ab, kommen seine ursprüngliche Meldung und sein Status unverändert durch.

Retry-Regel je Code

Welche Antworten eine Wiederholung wert sind, welche nicht und wie lange zu warten ist, steht dokumentiert statt im Ausprobieren.

error.json
"errors": {
"type": "invalid_parameters",
"statusCode": 400,
"message": "Invalid parameters, please check
the validationErrors array.",
"context": {
"targetSystem": "snelstart",
"unifiedApi": "Accounting"
},
"validationErrors": [
"Contact type must be COMPANY."
]
}

Das Gewicht tragen statusCode und downstreamErrors, und das eine ist genau deshalb normalisiert, damit das andere es nicht sein muss. HTTP ist genau darin, welcher Code zu welcher Lage gehört, und Systeme setzen das so lose um wie alles andere: Ein Validierungsfehler, den keine Wiederholung behebt, kommt von manchen Systemen als 500 zurück. Eine 500 sagt das Gegenteil, nämlich dass auf ihrer Seite etwas kaputtging und dieselbe Anfrage in zehn Minuten durchaus gelingen kann. Maesn antwortet mit dem Code, den die Lage wirklich verlangt, Ihre Retry-Logik liest also eine Kategorie statt eines Irrtums.

Den Code zu korrigieren würde Sie sonst das kosten, was darunter liegt, und das ist oft der einzig nützliche Teil: welches Feld abgewiesen wurde, was das System stattdessen erwartet hat, oder ein eigener Status, der nur dort etwas bedeutet. Das Original wird deshalb nicht ersetzt. Es reist neben dem korrigierten in downstreamErrors, und darum kann Ihre Anwendung auf die Kategorie verzweigen, während ein Entwickler die eigenen Worte des Systems liest, statt dass das eine gegen das andere getauscht wird.

Nicht jedes Problem antwortet mit einem Fehler. Ein Aufruf kann gelingen und trotzdem nicht alles tun, worum Sie gebeten haben, und das kommt als meta.warnings in der Antwort an: ein Feld, das das Zielsystem nicht nutzt, oder ein Wert, den es übergeht, weil es ihn nicht kennt, etwa eine Währung außerhalb der von ihm behandelten. Geschrieben ist das für die anbindenden Entwickler und nicht für den Endnutzer, und es trennt einen Schreibvorgang, der funktioniert hat, von einem, der so funktioniert hat, wie Sie es meinten.

Fehlertypen

Zehn Typen, fünf Entscheidungen

Das Feld type ist der Teil, gegen den zu bauen sich lohnt. Zehn standardisierte Werte decken jeden Fehler ab, den die Unified API erzeugt, und jeder verlangt eine andere Reaktion: beheben und erneut senden, den Kunden zum Neuverbinden bitten, aufhören, weil es den Endpunkt für dieses System nicht gibt, oder abwarten und später versuchen. Sie so zu gruppieren macht aus der Fehlerbehandlung statt eines Haufens Sonderfälle vier oder fünf Zweige, die Sie einmal schreiben.

Was es bewusst nicht tut, ist das Detail einzuebnen. Ein Rate-Limit eines Zielsystems kommt als eigener Typ an, statt in einem allgemeinen Fehlschlag aufzugehen, weil die richtige Reaktion sich von der auf einen Serverfehler unterscheidet und weil das Limit dem Zielsystem gehört und von Ihnen zu achten ist. Die Taktung läuft auf den asynchronen Endpunkten, bei einem synchronen Aufruf ist der Typ also das ganze Signal. Eine abgelaufene Verbindung kommt ebenfalls als eigener Typ an, denn die Lösung ist keine Wiederholung, sondern ein Kunde, der erneut durch die Authentifizierung geht.

Ihre Anfrage

Beheben und erneut senden

invalid_parametersconflict

Berechtigung

Der Kunde verbindet neu

not_authorizedinactive_usertarget_system_credentials_error

Nicht verfügbar

Nicht wiederholen, es erscheint nicht

resource_not_supportedtarget_system_not_found

Das Zielsystem

Den Downstream-Fehler lesen

target_system_errortarget_system_rate_limit_error

Vorübergehend

Abwarten und wiederholen

service_unavailable
Retries und Ausfälle

Was Sie erneut versuchen, und was nie

Den falschen Fehler zu wiederholen verschwendet Verkehr und verdeckt einen echten Fehler. Den richtigen zu wiederholen ist oft der Unterschied zwischen einem gescheiterten und einem langsamen Abgleich.

429Vom System gedrosseltRetryEine Minute warten, dann die Wartezeit verdoppeln
500Interner ServerfehlerRetry15 bis 30 Sekunden warten, dann exponentiell zurückgehen
503Zielsystem nicht erreichbarRetry15 bis 30 Sekunden warten, dann exponentiell zurückgehen
400Nutzlast hat die Prüfung verfehltKein RetryDie Felder aus validationErrors beheben und erneut senden
401Zugangsdaten nicht mehr gültigKein RetryDen Kunden die Anbindung neu verbinden lassen
409Die Ressource existiert schonKein RetryDen Anfragerumpf prüfen, bevor Sie erneut senden

Hier arbeiten zwei Ebenen, und es lohnt sich, sie auseinanderzuhalten, angefangen damit, dass die Tabelle darüber für Ihren Code geschrieben ist und nicht unseren beschreibt. Maesns Ebene ist die Einordnung: Der Fehler kommt mit einer Kategorie an, mit benanntem System und mit angehängter ursprünglicher Antwort, und ungültige Eingaben werden gefangen, bevor sie je ein System erreichen. Die Wiederholung liegt bei Ihnen. Maesn wiederholt und taktet auf den asynchronen Endpunkten, und bei einem synchronen Aufruf gehen die 429, 500 und 503 des Zielsystems direkt durch, damit Ihre Anwendung darauf reagiert. Dieselbe Warteschlange gibt die Anfragen eines Mandanten der Reihe nach frei, und das verhindert, dass sich zwei Token-Refreshes überschneiden und Ihren Kunden eine erneute Authentifizierung kosten.

Wenn Sie doch wissen müssen, was auf der Leitung wirklich geschah, sind die Anfrage, die Antwort und jedes Event darum herum aufgezeichnet, einen sporadischen Fehler zu untersuchen heißt also, ihn über Protokollierung und Monitoring nachzuschlagen statt ihn nachzustellen.

Warum es zählt

Ein Fehlerpfad, jedes System

Selbst gebaut
  • Je System eine andere Fehlerform parsen
  • Raten, welche Fehler wiederholbar sind
  • Die Originalmeldung unterwegs verlieren
  • Ungültige Eingaben erst vom System erfahren
Mit Maesn
  • Ein Umschlag mit echter Kategorie
  • Retry-Regel je Antwortcode
  • Downstream-Fehler durchgereicht
  • Ungültige Eingaben vor dem Senden gefangen

Bei der Fehlerbehandlung verlieren Integrationsprojekte still ihre Marge. Nicht im ersten Bau, sondern im zweiten Jahr, wenn jedes neue System einem Support-Runbook, das niemand verantworten will, einen weiteren Fehlerdialekt hinzufügt und ein Kunde fragt, warum seine Rechnung nicht abgeglichen wurde. Weil Umschlag, Kategorien und Retry-Regel Maesns sind und nicht die jedes Herstellers, wird dieses Runbook einmal geschrieben und hört auf zu wachsen. Das System, das Ihr Kunde als nächstes wählt, ändert, welches Logo an der Verbindung steht, nicht wie Ihr Code mit einem schlechten Tag umgeht. Das Runbook, das aufhört zu wachsen, ist auch das, aus dem Customer-Success-Teams arbeiten müssen, wenn ein Kunde schon in der Leitung ist.

FAQ Unified Error Handling

Häufige Fragen

Wie sieht ein Maesn-Fehler aus?

Jeder Fehler kommt in einem errors-Objekt auf oberster Ebene an, mit einem standardisierten type, dem HTTP-statusCode, einer kurzen lesbaren message und einem context-Block, der Zielsystem, Unified API und einen Zeitstempel nennt. Je nach Typ trägt er zusätzlich validationErrors oder downstreamErrors. Weil die Form nie wechselt, deckt ein Handler jedes System ab.

Warum zählt der standardisierte type?

Weil Sie damit auf die Fehlerart verzweigen statt Prosa zu parsen. Ungültige Eingaben, eine abgelaufene Verbindung, ein nicht unterstützter Endpunkt, ein Rate-Limit und ein vorübergehender Ausfall sind verschiedene Lagen, die verschiedene Reaktionen brauchen, und auf einer rohen API kommen sie oft als derselbe Statuscode mit anderem Wortlaut an. Der type trennt sie auf jedem System gleich.

Was sind Validierungsfehler?

Eingabeprobleme, die Maesn erkennt, bevor die Anfrage das Zielsystem erreicht. Feldformate, Pflichtwerte und Datentypen werden zuerst geprüft, und alles Fehlerhafte steht in validationErrors mit Feld und kurzer Meldung. Sie beheben die benannten Felder und senden erneut, statt vom nachgelagerten System in dessen Wortlaut davon zu erfahren.

Verliere ich den ursprünglichen Fehler des Systems?

Nein. Lautet der Fehlertyp target_system_error, werden die eigene Fehlerantwort des Systems und sein HTTP-Status wörtlich in downstreamErrors durchgereicht. Sie bekommen eine normalisierte Kategorie zum Verzweigen und das rohe Herstellerdetail zum Debuggen, statt des einen auf Kosten des anderen.

Welche Fehler sollte ich wiederholen?

429, 500 und 503 sind eine Wiederholung mit exponentiellem Backoff wert. Bei 429 beginnen Sie mit einer Minute Wartezeit, bei 500 und 503 mit 15 bis 30 Sekunden, und verdoppeln die Wartezeit mit jedem Versuch, bis Sie eine Schwelle erreichen, ab der die Anfrage als gescheitert gilt. Beachten Sie einen Retry-After-Header, wenn einer da ist. Die 4xx-Codes, die ein Problem der Anfrage selbst beschreiben, etwa 400, 401, 403, 404, 405 und 409, gehören nicht wiederholt, weil dieselbe Anfrage gleich scheitern wird.

Was passiert bei einem Ausfall eines Zielsystems?

Ein vorübergehend nicht erreichbarer Zielendpunkt erscheint als 503 mit dem Typ service_unavailable, und das ist das Signal, abzuwarten und zu wiederholen, statt den Schreibvorgang als verloren zu behandeln. Maesn beobachtet die verbundenen Systeme und ihre Endpunkte, ein Ausfall fällt hier also meist zuerst auf, und Ihr Ansprechpartner sagt Ihnen Bescheid, statt ihn als stillen Fehler auftauchen zu lassen. Das Abwarten planen Sie bei einem synchronen Aufruf selbst, und die Wiederholung mit ihm.

Woran erkenne ich, dass ein Wert übergangen statt abgewiesen wurde?

An meta.warnings in der Antwort. Ein Aufruf kann gelingen und trotzdem nicht alles tun, worum Sie gebeten haben: Ein Feld, das das Zielsystem nicht nutzt, oder ein Wert, den es übergeht, weil es ihn nicht kennt, wird dort benannt statt zu verschwinden. Geschrieben ist das für die anbindenden Entwickler und nicht für den Endnutzer, und es trennt einen Schreibvorgang, der funktioniert hat, von einem, der so funktioniert hat, wie Sie es meinten.

Was, wenn eine Verbindung abläuft?

Sie erhalten eine 401 mit dem Typ not_authorized. Ursachen sind ein fehlender oder falscher Key, im Zielsystem entzogener Zugriff oder abgelaufene Token, und manche Systeme begrenzen die Lebensdauer eines Refresh-Tokens, etwa auf dreißig Tage, die erneute Authentifizierung gehört also in den Entwurf statt in die Sonderfälle. Behandeln Sie die 401, indem Sie den Kunden zügig zum Neuverbinden auffordern.

Wie unterscheide ich einen nicht unterstützten von einem defekten Endpunkt?

Am type. resource_not_supported heißt, dass der Endpunkt für dieses eine System nicht umgesetzt ist, eine Wiederholung hilft also nie, und die Antwort ist ein anderer Weg für diese Anbindung. Ein target_system_error heißt, dass der Aufruf gültig war, das System ihn aber abgewiesen hat oder daran gescheitert ist, und das Downstream-Detail sagt Ihnen warum.

Einmal bauen, auf der Unified API.

Sehen Sie, wie Unified Error Handling für Ihre Integration funktioniert, oder steigen Sie in die technische Referenz ein.