Fehler

Dieses Kapitel gibt einen Überblick über das Fehlermodell für Google APIs. Es bietet auch eine allgemeine Anleitung dazu, wie Entwickler Fehler ordnungsgemäß generieren und beheben können.

Google APIs verwenden ein einfaches protokollunabhängiges Fehlermodell, das es ermöglicht, eine konsistente Umgebung innerhalb unterschiedlicher APIs, API-Protokolle wie gRPC oder HTTP und Fehlerkontexte (z. B. Asynchronitäten, Batch- oder Workflow-Fehler) zu schaffen.

Fehlermodell

Das Fehlermodell wird logisch durch google.rpc.Status definiert. Diese Instanz wird bei einem API-Fehler an den Client zurückgegeben. Das folgende Code-Snippet zeigt den allgemeinen Aufbau des Fehlermodells:

package google.rpc;

message Status {
  // A simple error code that can be easily handled by the client. The
  // actual error code is defined by `google.rpc.Code`.
  int32 code = 1;

  // A developer-facing human-readable error message in English. It should
  // both explain the error and offer an actionable resolution to it.
  string message = 2;

  // Additional error information that the client code can use to handle
  // the error, such as retry delay or a help link.
  repeated google.protobuf.Any details = 3;
}

Da die meisten Google APIs ein ressourcenorientiertes API-Design verwenden, erfolgt auch die Fehlerbehebung nach diesem Designprinzip. Dabei wird ein kleiner Satz von Standardfehlern für eine große Anzahl von Ressourcen genutzt. Anstatt beispielsweise verschiedene Arten von "nicht gefundenen" Fehlern zu definieren, verwendet der Server einen Standardfehlercode google.rpc.Code.NOT_FOUND und teilt dem Client mit, welche Ressource nicht gefunden wurde. Der verhältnismäßig kleine Zustandsbereich vereinfacht die Dokumentation und die Clientlogik. Außerdem sind bessere idiomatische Zuordnungen in Clientbibliotheken möglich und umsetzbare Informationen lassen sich uneingeschränkt einbeziehen.

Fehlercodes

Google APIs müssen die von google.rpc.Code definierten kanonischen Fehlercodes verwenden. In den einzelnen APIs sollten keine zusätzlichen Fehlercodes definiert werden, da Entwickler in der Regel keine Logiken zur Verarbeitung einer großen Anzahl von Fehlercodes schreiben. Beispiel: Bei der Verarbeitung von durchschnittlich drei Fehlercodes pro API-Aufruf würde der Großteil der Anwendungslogik nur für die Fehlerbehebung genutzt werden, was für keine gute Entwicklerumgebung spricht.

Fehlermeldungen

Fehlermeldungen sollen Nutzern helfen, API-Fehler schnell und einfach zu verstehen und zu beheben. Beachten Sie beim Schreiben von Fehlermeldungen generell die folgenden Richtlinien:

  • Gehen Sie nicht davon aus, dass Nutzer API-Experten sind. Nutzer können Cliententwickler, Betriebspersonal, IT-Mitarbeiter oder Endnutzer von Anwendungen sein.
  • Gehen Sie nicht davon aus, dass Nutzer etwas über Ihre Dienstimplementierung wissen oder mit Fehlerkontexten wie etwa Log-Analysen vertraut sind.
  • Fehlermeldungen sollten nach Möglichkeit so konstruiert sein, dass auch technische Nutzer, die keine Entwickler Ihrer API sind, auf den Fehler reagieren und ihn beheben können.
  • Halten Sie Fehlermeldungen kurz. Geben Sie bei Bedarf einen Link an, über den Nutzer Fragen stellen, Feedback geben oder weitere Informationen erhalten können, die den Rahmen der Fehlermeldung an sich sprengen würden. Verwenden Sie andernfalls das erweiterbare Detailfeld.

Fehlerdetails

Google APIs definieren eine Reihe standardmäßiger Fehlernutzlasten für Fehlerdetails. Sie finden diese unter google/rpc/error_details.proto. Fehlerdetails decken die gängigsten Anforderungen für API-Fehler wie Kontingentfehler und ungültige Parameter ab. Wie Fehlercodes sollten Entwickler diese Standardnutzlasten nach Möglichkeit verwenden.

Zusätzliche Fehlerdetailtypen sollten nur eingeführt werden, wenn sie ergänzend zum Anwendungscode zur Fehlerbehebung beitragen. Wenn die Fehlerinformationen nur von Nutzern verarbeitet werden, geben Sie den Fehlermeldungsinhalt an und lassen Sie Entwickler den Fehler manuell beheben, anstatt zusätzliche Fehlerdetailtypen einzuführen.

Hier einige Beispiele für error_details-Nutzlasten:

  • RetryInfo beschreibt, wann Clients eine fehlgeschlagene Anfrage wiederholen können. Die Rückgabe erfolgt gegebenenfalls bei Code.UNAVAILABLE oder Code.ABORTED.
  • QuotaFailure beschreibt, wie eine Kontingentprüfung fehlgeschlagen ist. Die Rückgabe erfolgt gegebenenfalls bei Code.RESOURCE_EXHAUSTED.
  • BadRequest beschreibt Verstöße in einer Clientanfrage. Die Rückgabe erfolgt gegebenenfalls bei Code.INVALID_ARGUMENT.
  • ErrorInfo stellt strukturierte Fehlerinformationen bereit, die sowohl stabil als auch erweiterbar sind.

Fehlerinformation

ErrorInfo ist eine der Standardfehlernutzlasten. Sie bietet stabile und erweiterbare Fehlerinformationen, auf die sich sowohl Menschen als auch Anwendungen verlassen können. Jedes ErrorInfo enthält drei Informationen: eine Fehlerdomain, einen Fehlergrundsatz und eine Reihe von Fehlermetadaten. Weitere Informationen finden Sie in der Definition der ErrorInfo.

HTTP-Zuordnung

Während Proto3-Nachrichten einen nativen JSON-Codierung haben, verwendet die Google API Platform aus Gründen der Abwärtskompatibilität ein anderes Fehlerschema für Google REST APIs.

Schema:

// The error schema for Google REST APIs. NOTE: this schema is not used for
// other wire protocols.
message Error {
  // This message has the same semantics as `google.rpc.Status`. It has an extra
  // field `status` for backward compatibility with Google API Client Library.
  message Status {
    // This corresponds to `google.rpc.Status.code`.
    int32 code = 1;
    // This corresponds to `google.rpc.Status.message`.
    string message = 2;
    // This is the enum version for `google.rpc.Status.code`.
    google.rpc.Code status = 4;
    // This corresponds to `google.rpc.Status.details`.
    repeated google.protobuf.Any details = 5;
  }
  // The actual error payload. The nested message structure is for backward
  // compatibility with Google API client libraries. It also makes the error
  // more readable to developers.
  Status error = 1;
}

Beispiel:

{
  "error": {
    "code": 401,
    "message": "Request had invalid credentials.",
    "status": "UNAUTHENTICATED",
    "details": [{
      "@type": "type.googleapis.com/google.rpc.RetryInfo",
      ...
    }]
  }
}

RPC-Zuordnung

Das Fehlermodell wird von unterschiedlichen RPC-Protokollen auf unterschiedliche Weise zugeordnet. Hinsichtlich gRPC wird das Fehlermodell nativ durch den generierten Code und die Laufzeitbibliothek in den verfügbaren Sprachen unterstützt. Weitere Informationen finden Sie in der API-Dokumentation für gRPC. Sehen Sie sich beispielsweise das io.grpc.Status von gRPC Java an.

Clientbibliothek-Zuordnung

Google-Clientbibliotheken können Fehler je nach Sprache unterschiedlich wiedergeben, um den gängigen Dialekten gerecht zu werden. Beispielsweise gibt die Bibliothek google-cloud-go einen Fehler zurück, der dieselbe Schnittstelle wie google.rpc.Status implementiert, während google-cloud-java eine Ausnahme auslöst.

Fehlerlokalisierung

Das Feld message in google.rpc.Status ist für Entwickler bestimmt und muss auf Englisch sein.

Wenn Sie eine Fehlermeldung für Nutzer benötigen, verwenden Sie google.rpc.LocalizedMessage als Detailfeld. Das Nachrichtenfeld in google.rpc.LocalizedMessage kann lokalisiert werden. Achten Sie darauf, dass das Nachrichtenfeld in google.rpc.Status auf Englisch ist.

Standardmäßig sollte der API-Dienst das Gebietsschema des authentifizierten Nutzers oder den HTTP Accept-Language-Header verwenden, um die Sprache für die Lokalisierung zu bestimmen.

Fehlerbehebung

In der nachfolgenden Tabelle sind alle gRPC-Fehlercodes aufgeführt, die in google.rpc.Code definiert sind, und eine kurze Beschreibung ihrer Ursache. Zur Fehlerbehebung können Sie die Beschreibung des zurückgegebenen Statuscodes prüfen und den Aufruf entsprechend ändern.

HTTP RPC Beschreibung
200 OK Kein Fehler
400 INVALID_ARGUMENT Der Client hat ein ungültiges Argument angegeben. Weitere Informationen finden Sie in der Fehlermeldung und den Fehlerdetails.
400 FAILED_PRECONDITION Die Anfrage, wie etwa das Löschen eines Verzeichnisses mit Inhalt, kann im aktuellen Systemzustand nicht ausgeführt werden.
400 OUT_OF_RANGE Der Client hat einen ungültigen Bereich angegeben.
401 UNAUTHENTICATED Die Anfrage konnte aufgrund eines fehlenden, ungültigen oder abgelaufenen OAuth-Tokens nicht authentifiziert werden.
403 PERMISSION_DENIED Der Client verfügt nicht über die erforderliche Berechtigung. Dies kann vorkommen, wenn das OAuth-Token nicht über die richtigen Bereiche verfügt, der Client keine Berechtigung besitzt oder die API nicht für das Clientprojekt aktiviert wurde.
404 NOT_FOUND Eine angegebene Ressource wurde nicht gefunden oder die Anfrage wurde ohne Angabe von Gründen abgelehnt, beispielsweise, weil die Ressource auf die weiße Liste gesetzt wurde.
409 ABORTED Gibt einen Konflikt aufgrund von gleichzeitig ausgeführten Aktionen an, wie etwa einen Read-Modify-Write-Konflikt.
409 ALREADY_EXISTS Die von einem Client zu erstellende Ressource ist bereits vorhanden.
429 RESOURCE_EXHAUSTED Entweder wurde das Ressourcenkontingent überschritten oder das Ratenlimit erreicht. Der Client sollte in den Fehlerdetails zu google.rpc.QuotaFailure nach weiteren Informationen suchen.
499 CANCELLED Request cancelled by the client.
500 DATA_LOSS Dauerhafter Datenverlust oder Datenkorruption. Der Client sollte den Fehler dem Nutzer melden.
500 UNKNOWN Unbekannter Serverfehler. In der Regel ein Serverprogrammfehler.
500 INTERNAL Interner Serverfehler. In der Regel ein Serverprogrammfehler.
501 NOT_IMPLEMENTED Die API-Methode wurde vom Server nicht implementiert.
503 UNAVAILABLE Dienst nicht verfügbar. In der Regel ist der Server ausgefallen.
504 DEADLINE_EXCEEDED Die Frist der Anfrage wurde überschritten. Dies geschieht nur, wenn für den Aufruf eine Frist festgelegt wurde, die kürzer ist als die Standardfrist der Methode (d. h., die angeforderte Frist reicht nicht aus, damit der Server die Anfrage bearbeitet), und die Anfrage nicht innerhalb der Frist abgeschlossen wurde.

Wiederholungen nach Fehlern

Clients können bei 503 NICHT VERFÜGBAREN Fehlern mit exponentiellem Backoff den Vorgang wiederholen. Die Mindestverzögerung sollte 1 Sekunde betragen, sofern nicht anders angegeben.

Bei 429 RESOURCE_EXHAUSTED-Fehlern kann der Client den Versuch mit einer Verzögerung von mindestens 30 Sekunden auf der höheren Ebene wiederholen. Solche Wiederholungsversuche sind nur für lang andauernde Hintergrundjobs nützlich.

Bei allen anderen Fehlern ist keine Wiederholung möglich. Stellen Sie zuerst sicher, dass Ihre Anfrage idempotent ist, und lesen Sie die Anleitung unter google.rpc.RetryInfo.

Fehlerfortpflanzung

Wenn der API-Dienst von anderen Diensten abhängt, sollten Sie Fehler von diesen Diensten nicht ungesehen an Ihre Clients weitergeben. Wir empfehlen beim Übersetzen von Fehlern Folgendes:

  • Blenden Sie Details zur Implementierung sowie vertrauliche Informationen aus.
  • Passen Sie die für den Fehler zuständige Partei an. Beispielsweise sollte ein Server, der von einem anderen Dienst den Fehler INVALID_ARGUMENT empfängt, an seinen eigenen Aufrufer den Fehler INTERNAL weiterleiten.

Fehler generieren

Wenn Sie Serverentwickler sind, sollten Sie Fehler mit ausreichenden Informationen generieren, damit Cliententwickler das Problem verstehen und beheben können. Gleichzeitig müssen Sie die Sicherheit und Vertraulichkeit der Nutzerdaten berücksichtigen und die Offenlegung vertraulicher Informationen in der Fehlermeldung und den Fehlerdetails vermeiden. Der Grund dafür ist, dass Fehler häufig protokolliert werden und gegebenenfalls für andere Nutzer zugänglich sind. Eine Fehlermeldung wie "Client IP address is not on allowlist 18.0.0.0.0/8" liefert beispielsweise Informationen zur serverseitigen Richtlinie, auf die der Nutzer möglicherweise nicht zugreifen kann.

Um korrekte Fehler zu generieren, müssen Sie zuerst mit google.rpc.Code vertraut sein, um den am besten geeigneten Fehlercode für jede Fehlerbedingung auszuwählen. Eine Serveranwendung kann mehrere Fehlerbedingungen parallel prüfen und die erste zurückgeben.

In der folgenden Tabelle sind die Fehlercodes mit je einem Beispiel einer guten Fehlermeldung aufgeführt.

HTTP RPC Beispiel für Fehlermeldung
400 INVALID_ARGUMENT Request field x.y.z is xxx, expected one of [yyy, zzz].
400 FAILED_PRECONDITION Resource xxx is a non-empty directory, so it cannot be deleted.
400 OUT_OF_RANGE Parameter 'age' is out of range [0, 125].
401 UNAUTHENTICATED Invalid authentication credentials.
403 PERMISSION_DENIED Permission 'xxx' denied on resource 'yyy'.
404 NOT_FOUND Resource 'xxx' not found.
409 ABORTED Couldn’t acquire lock on resource ‘xxx’.
409 ALREADY_EXISTS Resource 'xxx' already exists.
429 RESOURCE_EXHAUSTED Quota limit 'xxx' exceeded.
499 CANCELLED Request cancelled by the client.
500 DATA_LOSS See note.
500 UNKNOWN See note.
500 INTERNAL See note.
501 NOT_IMPLEMENTED Method 'xxx' not implemented.
503 UNAVAILABLE See note.
504 DEADLINE_EXCEEDED Siehe Hinweis.

Das Paket google.rpc definiert eine Reihe von Standardfehlernutzlasten, die benutzerdefinierten Fehlernutzlasten vorgezogen werden. In der folgenden Tabelle sind die Fehlercodes und deren standardmäßige Fehlernutzlast aufgelistet, falls zutreffend.

HTTP RPC Empfohlenes Fehlerdetail
400 INVALID_ARGUMENT google.rpc.BadRequest
400 FAILED_PRECONDITION google.rpc.PreconditionFailure
400 OUT_OF_RANGE google.rpc.BadRequest
401 UNAUTHENTICATED
403 PERMISSION_DENIED
404 NOT_FOUND google.rpc.ResourceInfo
409 ABORTED
409 ALREADY_EXISTS google.rpc.ResourceInfo
429 RESOURCE_EXHAUSTED google.rpc.QuotaFailure
499 CANCELLED
500 DATA_LOSS
500 UNKNOWN
500 INTERNAL
501 NOT_IMPLEMENTED
503 UNAVAILABLE
504 DEADLINE_EXCEEDED