Erreurs

Ce chapitre les principaux aspects du modèle d'erreur pour les API Google. Il fournit également des conseils généraux aux développeurs sur la manière de générer et de gérer correctement les erreurs.

Les API Google utilisent un modèle d'erreur simple indépendant du protocole, qui nous permet d'offrir une expérience cohérente entre différentes API, différents protocoles d'API (tels que gRPC ou HTTP) et différents contextes d'erreur (par exemple, erreurs asynchrones, par lots ou de workflow).

Modèle d'erreur

Le modèle d'erreur pour les API Google est défini de manière logique par google.rpc.Status, dont une instance est renvoyée au client lorsqu'une erreur d'API se produit. L'extrait de code suivant montre la conception générale du modèle d'erreur :

package google.rpc;

// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs.
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 info or a help link.
  repeated google.protobuf.Any details = 3;
}

Étant donné que la plupart des API Google utilisent une conception d'API axée sur les ressources, la gestion des erreurs suit le même principe de conception en utilisant un petit ensemble d'erreurs standards avec un grand nombre de ressources. Par exemple, au lieu de définir différents types d'erreurs "introuvables", le serveur utilise un code d'erreur google.rpc.Code.NOT_FOUND standard et indique au client quelle ressource spécifique est introuvable. Le plus petit espace d'erreur réduit la complexité de la documentation, offre de meilleurs mappages idiomatiques dans les bibliothèques clientes et réduit la complexité de la logique du client tout en ne limitant pas l'inclusion d'informations exploitables.

Codes d'erreur

Les API Google doivent utiliser les codes d'erreur canoniques définis par google.rpc.Code. Les API individuelles doivent éviter de définir des codes d'erreur supplémentaires, car il est très peu probable que les développeurs écrivent une logique pour gérer un grand nombre de codes d'erreur. À titre de référence, gérer en moyenne trois codes d'erreur par appel d'API signifierait que la plupart de la logique d'application ne concernerait que la gestion des exceptions, ce qui ne serait pas une bonne expérience pour les développeurs.

Messages d'erreur

Le message d'erreur devrait aider les utilisateurs à comprendre et résoudre l'erreur d'API facilement et rapidement. En général, tenez compte des instructions suivantes lors de la rédaction des messages d'erreur :

  • Ne partez pas du principe que l'utilisateur est un expert de votre API. Ces utilisateurs peuvent être des développeurs clients, des responsables des opérations, du personnel informatique ou des utilisateurs finaux d'applications.
  • Ne partez pas du principe que l'utilisateur connaît la mise en œuvre de votre service ou qu'il connaît le contexte des erreurs (tel que l'analyse du journal).
  • Dans la mesure du possible, les messages d'erreur doivent être construits de manière à ce qu'un utilisateur technique (mais pas nécessairement un développeur de votre API) puisse répondre à l'erreur et la corriger.
  • Veillez à rédiger un message d'erreur concis. Si nécessaire, fournissez un lien permettant à un lecteur en difficulté de poser des questions, de faire des commentaires ou d’obtenir plus d’informations qui ne correspondent pas parfaitement à un message d’erreur. Sinon, utilisez le champ de détails pour développer.

Informations relatives à l'erreur

Les API Google définissent un ensemble de charges utiles d'erreur standard pour les informations relatives à l'erreur, que vous pouvez trouver dans google/rpc/error_details.proto. Elles couvrent les besoins les plus courants d'erreurs d'API, tels que les échecs de quota et les paramètres non valides. À l'instar des codes d'erreur, les développeurs doivent utiliser ces charges utiles standards dès que possible.

Certains types de détails d'erreur supplémentaires ne doivent être introduits que s'ils peuvent aider le code d'application à gérer les erreurs. Si les informations relatives à l'erreur ne peuvent être traitées que par des humains, utilisez le contenu du message d'erreur et laissez les développeurs le gérer manuellement plutôt que d'introduire des types de détails d'erreur supplémentaires.

Voici quelques exemples de charges utiles error_details :

  • ErrorInfo fournit des informations sur les erreurs structurées qui sont à la fois stables et extensibles.
  • RetryInfo : décrit quand les clients peuvent réessayer une requête ayant échoué. Elle peut être renvoyée dans Code.UNAVAILABLE ou Code.ABORTED.
  • QuotaFailure : décrit comment une vérification de quota a échoué. Elle peut être renvoyée dans Code.RESOURCE_EXHAUSTED.
  • BadRequest : décrit les violations dans une requête client. Elle peut être renvoyée dans Code.INVALID_ARGUMENT.

Information sur l'erreur

ErrorInfo est un type particulier de charge utile d'erreur. Elle fournit des informations d'erreur stables et extensibles dont les utilisateurs et les applications peuvent dépendre. Chaque ErrorInfo comporte trois informations: un domaine d'erreur, un motif d'erreur et un ensemble de métadonnées d'erreur, comme cet exemple. Pour en savoir plus, consultez la définition de ErrorInfo.

Pour les API Google, le domaine d'erreur principal est googleapis.com, et les motifs d'erreur correspondants sont définis par l'énumération google.api.ErrorReason. Pour plus d'informations, consultez la définition google.api.ErrorReason.

Localisation des erreurs

Le champ message dans google.rpc.Status est destiné aux développeurs et doit être en anglais.

Si un message d'erreur adressé à l'utilisateur est nécessaire, utilisez google.rpc.LocalizedMessage en tant que champ de détails. Bien que le champ de message dans google.rpc.LocalizedMessage puisse être localisé, assurez-vous que ce même champ dans google.rpc.Status est en anglais.

Par défaut, le service d'API doit utiliser les paramètres régionaux ou l'en-tête Accept-Language de l'utilisateur authentifié, ou le paramètre language_code dans la requête pour déterminer la langue de la localisation.

Mappage des erreurs

Les API Google sont accessibles dans différents environnements de programmation. Chaque environnement dispose généralement de sa propre façon de traiter les erreurs. Les sections suivantes expliquent comment le modèle d'erreur est mappé dans les environnements couramment utilisés.

Mappage HTTP

Bien que les messages proto3 aient un codage JSON natif, la plate-forme d'API Google utilise un schéma d'erreur différent pour les API HTTP JSON de Google pour des raisons de rétrocompatibilité.

Schéma :

// This message defines the error schema for Google's JSON HTTP APIs.
message Error {
  // Deprecated. This message is only used by error format v1.
  message ErrorProto {}
  // This message has the same semantics as `google.rpc.Status`. It uses HTTP
  // status code instead of gRPC status code. It has extra fields `status` and
  // `errors` for backward compatibility with [Google API Client
  // Libraries](https://developers.google.com/api-client-library).
  message Status {
    // The HTTP status code that corresponds to `google.rpc.Status.code`.
    int32 code = 1;
    // This corresponds to `google.rpc.Status.message`.
    string message = 2;
    // Deprecated. This field is only used by error format v1.
    repeated ErrorProto errors = 3;
    // 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](https://developers.google.com/api-client-library). It also
  // makes the error more readable to developers.
  Status error = 1;
}

Exemple (lien) :

{
  "error": {
    "code": 400,
    "message": "API key not valid. Please pass a valid API key.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "API_KEY_INVALID",
        "domain": "googleapis.com",
        "metadata": {
          "service": "translate.googleapis.com"
        }
      }
    ]
  }
}

Mappage gRPC

Différents protocoles RPC mettent en correspondance le modèle d'erreur différemment. Pour gRPC, le modèle d'erreur est compatible de façon native par le code généré et la bibliothèque d'exécution dans chaque langage disponible. Pour en savoir plus, consultez la documentation de l'API de gRPC. Par exemple, consultez le statut Java io.grpc.Status de gRPC.

Mappage avec la bibliothèque cliente

Les bibliothèques clientes de Google peuvent choisir de relever les erreurs différemment selon les langages pour les rendre conformes aux idiomes établis. Par exemple, la bibliothèque google-cloud-go renvoie une erreur qui met en œuvre la même interface que google.rpc.Status, alors que google-cloud-java génère une exception.

Traiter les erreurs

Vous trouverez ci-dessous un tableau contenant tous les codes d'erreur gRPC définis dans google.rpc.Code et une brève description de leur origine. Pour gérer une erreur, vous pouvez vérifier la description du code d'état renvoyé et modifier votre appel en fonction.

HTTP gRPC Description
200 OK Aucune erreur.
400 INVALID_ARGUMENT Le client a spécifié un argument incorrect. Consultez le message d'erreur et les détails de l'erreur pour plus d'informations.
400 FAILED_PRECONDITION La requête ne peut pas être exécutée dans l'état actuel du système, par exemple la suppression d'un répertoire non vide.
400 OUT_OF_RANGE Le client a spécifié une plage non valide.
401 UNAUTHENTICATED La requête n'a pas été authentifiée en raison d'un jeton OAuth manquant, non valide ou ayant expiré.
403 PERMISSION_DENIED Le client ne dispose pas d'une autorisation suffisante. Cela peut se produire lorsque le jeton OAuth ne dispose pas des champs d'application appropriés, car le client n'a pas d'autorisation ou car l'API n'a pas été activée.
404 NOT_FOUND Une ressource spécifiée est introuvable.
409 ABORTED Un conflit de simultanéité existe, tel qu'un conflit lecture-modification-écriture.
409 ALREADY_EXISTS La ressource qu'un client a essayé de créer existe déjà.
429 RESOURCE_EXHAUSTED Le quota de ressources est dépassé ou la limite du débit est atteinte. Pour plus d'informations, le client doit rechercher les détails de l'erreur google.rpc.QuotaFailure.
499 CANCELLED La demande a été annulée par le client.
500 DATA_LOSS Perte de données irrécupérable ou corruption de données. Le client doit signaler l'erreur à l'utilisateur.
500 UNKNOWN Erreur du serveur inconnue. Généralement un bug de serveur.
500 INTERNAL Erreur interne au serveur. Généralement un bug de serveur.
501 NOT_IMPLEMENTED Méthode d'API non mise en œuvre par le serveur.
502 Non disponible Une erreur réseau s'est produite avant d'atteindre le serveur. Généralement une panne de réseau ou une mauvaise configuration.
503 UNAVAILABLE Service indisponible. Généralement, le serveur est inactif.
504 DEADLINE_EXCEEDED Délai de requête dépassé. Cela se produira uniquement si l'appelant définit un délai plus court que le délai par défaut de la méthode (le délai demandé ne suffit pas pour que le serveur traite la demande) et si la requête ne s'est pas terminée dans le délai.

Effectuer de nouvelles tentatives à la suite d'erreurs

Les clients peuvent effectuer de nouvelles tentatives à la suite d'erreurs de type "503 UNAVAILABLE" avec un intervalle exponentiel entre les tentatives. Le délai minimum doit être égal à 1 s sauf indication contraire. La répétition par défaut des tentatives doit être fixée à une fois, sauf indication contraire.

Pour les erreurs de type "429 RESOURCE_EXHAUSTED", le client peut effectuer de nouvelles tentatives au niveau supérieur avec un délai minimal de 30 s. Ces tentatives ne sont utiles que pour les tâches en arrière-plan de longue durée.

Pour toutes les autres erreurs, il se peut que la nouvelle tentative ne s'applique pas. Assurez-vous d'abord que votre requête est idempotente et consultez la section google.rpc.RetryInfo pour obtenir des conseils.

Propager des erreurs

Si votre service d'API dépend d'autres services, vous ne devez pas propager aveuglément les erreurs de ces services à vos clients. Lors de la traduction des erreurs, nous suggérons de suivre les conseils suivants :

  • Masquez les détails de mise en œuvre et les informations confidentielles.
  • Ajustez la partie responsable de l'erreur. Par exemple, un serveur qui reçoit une erreur INVALID_ARGUMENT d'un autre service doit propager un élément INTERNAL à son propre appelant.

Reproduire des erreurs

Si vous ne parvenez pas à résoudre les erreurs via l'analyse des journaux et la surveillance, essayez de reproduire les erreurs avec un test simple et reproductible. Vous pouvez utiliser ce test pour collecter plus d'informations utiles au dépannage, que vous pouvez ensuite fournir lorsque vous contactez l'assistance technique.

Nous vous recommandons d'utiliser curl -v et les paramètres système pour reproduire les erreurs avec les API Google. Ensemble, ils peuvent reproduire presque toutes les requêtes d'API Google et vous fournir des informations de débogage détaillées. Pour plus d'informations, consultez les pages de documentation respectives de l'API que vous appelez.

Générer des erreurs

Si vous êtes un développeur de serveur, vous devez générer des erreurs avec suffisamment d'informations pour aider les développeurs du client à comprendre et à résoudre le problème. En même temps, vous devez être conscient de la sécurité et de la confidentialité des informations sur l'utilisateur et éviter de divulguer des informations sensibles dans le message d'erreur et les détails de l'erreur, car les erreurs sont souvent consignées et peuvent être accessibles par d'autres utilisateurs. Par exemple, un message d'erreur du type "L'adresse IP du client ne figure pas dans la liste blanche 128.0.0.0/8" expose des informations sur la stratégie côté serveur, qui peut être inaccessible pour l'utilisateur qui a accès au journaux.

Pour générer des erreurs appropriées, vous devez d'abord connaître google.rpc.Code pour choisir le code d'erreur le mieux adapté à chaque condition d'erreur. Une application de serveur peut vérifier plusieurs conditions d'erreur en parallèle et renvoyer la première.

Le tableau suivant répertorie chaque code d'erreur et un exemple de message d'erreur correct.

HTTP gRPC Exemple de message d'erreur
400 INVALID_ARGUMENT Le champ de requête xyz est xxx, le champ attendu doit être inclus dans la plage [yyy, zzz].
400 FAILED_PRECONDITION La ressource xxx est un répertoire non vide et ne peut donc pas être supprimée.
400 OUT_OF_RANGE Le paramètre "âge" est en dehors de la plage [0, 125].
401 UNAUTHENTICATED Identifiants d'authentification non valides.
403 PERMISSION_DENIED Autorisation "xxx" refusée sur la ressource "yyy".
404 NOT_FOUND Ressource 'xxx' introuvable.
409 ABORTED Impossible de verrouiller la ressource "xxx".
409 ALREADY_EXISTS La ressource "xxx" existe déjà.
429 RESOURCE_EXHAUSTED La limite du quota "xxx" est dépassée.
499 CANCELLED La demande a été annulée par le client.
500 DATA_LOSS Voir la remarque ci-dessous.
500 UNKNOWN Voir la remarque ci-dessous.
500 INTERNAL Voir la remarque ci-dessous.
501 NOT_IMPLEMENTED La méthode "xxx" n'a pas été mise en œuvre.
503 UNAVAILABLE Voir la remarque ci-dessous.
504 DEADLINE_EXCEEDED Voir la remarque ci-dessous.

Charges utiles d'erreur

Le package google.rpc définit un ensemble de charges utiles d'erreur standards, qui sont préférées aux charges utiles d'erreur personnalisées. Le tableau suivant répertorie chaque code d'erreur et sa charge utile d'erreur standard correspondante, le cas échéant. Nous recommandons aux applications avancées de rechercher ces charges utiles d'erreurs dans google.rpc.Status lorsqu'elles gèrent les erreurs.

HTTP gRPC Informations sur l'erreur recommandées
400 INVALID_ARGUMENT google.rpc.BadRequest
400 FAILED_PRECONDITION google.rpc.PreconditionFailure
400 OUT_OF_RANGE google.rpc.BadRequest
401 UNAUTHENTICATED google.rpc.ErrorInfo
403 PERMISSION_DENIED google.rpc.ErrorInfo
404 NOT_FOUND google.rpc.ResourceInfo
409 ABORTED google.rpc.ErrorInfo
409 ALREADY_EXISTS google.rpc.ResourceInfo
429 RESOURCE_EXHAUSTED google.rpc.QuotaFailure
499 CANCELLED
500 DATA_LOSS google.rpc.DebugInfo
500 UNKNOWN google.rpc.DebugInfo
500 INTERNAL google.rpc.DebugInfo
501 NOT_IMPLEMENTED
503 UNAVAILABLE google.rpc.DebugInfo
504 DEADLINE_EXCEEDED google.rpc.DebugInfo