Erreurs

Ce chapitre fournit une présentation du modèle d'erreur des API Google, ainsi que 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 et indépendant du protocole, qui permet d'offrir une expérience cohérente dans différentes API, des protocoles d'API tels que gRPC ou HTTP et des contextes d'erreur (par exemple, erreurs asynchrones, par lots ou de workflow).

Modèle d'erreur

Le modèle d'erreur est défini de façon 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;

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;
}

É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 n'a pas été trouvée. Le plus petit espace d'état 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 devraient é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. Pour référence, gérer en moyenne trois codes d'erreur par appel d'API signifierait que la plupart des logiques d'application concernent la gestion des erreurs, ce qui n'entraînerait 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 supposez pas que l'utilisateur est un expert de votre API. Les utilisateurs peuvent être des développeurs clients, des opérateurs, 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étails d'erreur 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 de nouveaux types de détails d'erreur.

Voici quelques exemples de charges utiles error_details :

  • RetryInfo décrit quand les clients peuvent réessayer une requête qui a é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

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 REST JSON de Google pour des raisons de rétrocompatibilité.

Schéma :

// 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;
}

Exemple :

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

Mappage RPC

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, 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 renverra une erreur mettant en œuvre la même interface que google.rpc.Status, tandis que google-cloud-java fera remonter une exception.

Localisation des erreurs

Le champ message dans google.rpc.Status est orienté développeur 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. Tandis que le champ de message dans google.rpc.LocalizedMessage peut être localisé, assurez-vous que le champ de message 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 HTTP de l'utilisateur authentifié pour déterminer la langue de la localisation.

Traiter les erreurs

Vous trouverez ci-dessous un tableau contenant tous les codes d'erreur gRPC définis dans google.rpc.Code ainsi qu'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 RPC 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 pour le projet du client.
404 NOT_FOUND Une ressource spécifiée est introuvable ou la requête est rejetée pour des raisons non divulguées, telles que l'ajout à une liste blanche.
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. Le client doit rechercher les informations sur l'erreur google.rpc.QuotaFailure pour en savoir plus.
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.
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 suite aux erreurs

Les clients devraient effectuer de nouvelles tentatives suite aux erreurs 500 et 503 avec un intervalle exponentiel entre les tentatives. Le délai minimum doit être égal à 1 s sauf indication contraire. Pour les erreurs 429, le client peut réessayer en respectant un délai minimum de 30 secondes. Pour toutes les autres erreurs, la nouvelle tentative peut ne pas être applicable. Assurez-vous d'abord que votre demande est idempotente et consultez le message d'erreur pour obtenir des conseils.

Propager une erreur

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.

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, auxquelles l'utilisateur peut ne pas accéder.

Pour générer des erreurs correctes, vous devez d'abord vous familiariser avec google.rpc.Code pour choisir le code d'erreur le plus approprié pour 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 RPC 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 le fichier "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.

REMARQUE : Étant donné que le client ne peut pas corriger l'erreur serveur, il n'est pas utile de générer d'autres informations relatives aux erreurs. Pour éviter la fuite d'informations sensibles en conditions d'erreur, nous vous recommandons de ne pas générer de message d'erreur et de ne générer que des informations relatives aux erreurs google.rpc.DebugInfo. L'élément DebugInfo est conçu spécifiquement pour la journalisation côté serveur et ne doit pas être envoyé au client.

Le package google.rpc définit un ensemble de charges utiles d'erreur standard, qui sont préférées aux charges d'erreur personnalisée. Le tableau suivant répertorie chaque code d'erreur et sa charge utile d'erreur standard correspondante, le cas échéant.

HTTP RPC 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
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
Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…