Errori

Questo capitolo fornisce una panoramica del modello di errore per le API di Google. Fornisce inoltre indicazioni generali agli sviluppatori su come generare e gestire correttamente gli errori.

Le API di Google utilizzano un semplice modello di errore indipendente dal protocollo, che ci consente di offrire un'esperienza coerente su diverse API, protocolli di API diversi (come gRPC o HTTP) e diversi contesti di errore (come errori asincroni, batch o di flusso di lavoro).

Modello di errore

Il modello di errore per le API di Google è definito logicamente da google.rpc.Status, un'istanza di cui viene restituita al client quando si verifica un errore dell'API. Il seguente snippet di codice mostra la progettazione complessiva del modello di errore:

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

Poiché la maggior parte delle API di Google utilizza una progettazione di API orientata alle risorse, la gestione degli errori segue lo stesso principio di progettazione utilizzando un piccolo insieme di errori standard con un numero elevato di risorse. Ad esempio, invece di definire tipi diversi di errori"non trovati", il server utilizza un codice di errore google.rpc.Code.NOT_FOUND standard e indica al client quale risorsa specifica non è stata trovata. Lo spazio di errore più piccolo riduce la complessità della documentazione, consente migliori mappature idiomatiche nelle librerie client e riduce la complessità della logica di client, senza limitare l'inclusione di informazioni strategiche.

Codici di errore

Le API di Google devono utilizzare i codici di errore canonici definiti da google.rpc.Code. Le singole API devono evitare di definire codici di errore aggiuntivi, poiché è molto improbabile che gli sviluppatori scrivano la logica per gestire un numero elevato di codici di errore. Per riferimento, la gestione di una media di tre codici di errore per chiamata API significherebbe che la maggior parte della logica dell'applicazione servirebbe solo per la gestione degli errori, il che non sarebbe una buona esperienza per sviluppatori.

Messaggi di errore

Il messaggio di errore dovrebbe aiutare gli utenti a comprendere e risolvere l'errore dell'API in modo semplice e veloce. In generale, considera le seguenti linee guida quando scrivi i messaggi di errore:

  • Non dare per scontato che l'utente sia un utente esperto della tua API. Gli utenti possono essere client sviluppatori, addetti alle operazioni, personale IT o utenti finali delle app.
  • Non dare per scontato che l'utente conosca qualcosa dell'implementazione del tuo servizio o che conosca il contesto degli errori (ad esempio, l'analisi dei log).
  • Quando possibile, i messaggi di errore devono essere creati in modo che un utente tecnico (ma non necessariamente uno sviluppatore della tua API) possa rispondere all'errore e correggerlo.
  • Mantieni breve il messaggio di errore. Se necessario, includi un link dove un lettore confuso possa porre domande, dare feedback o ricevere ulteriori informazioni che non rientrano in un messaggio di errore. In caso contrario, utilizza il campo dei dettagli per espanderlo.

Dettagli errore

Le API di Google definiscono un insieme di payload di errore standard per i dettagli degli errori, che puoi trovare in google/rpc/error_details.proto. Copreno le esigenze più comuni per gli errori dell'API, come l'errore di quota e i parametri non validi. Come i codici di errore, gli sviluppatori devono utilizzare questi payload standard ove possibile.

Altri tipi di dettagli sugli errori devono essere introdotti solo se possono contribuire a gestire il codice dell'applicazione per gli errori. Se le informazioni di errore possono essere gestite solo da persone, affidati ai contenuti dei messaggi di errore e lascia che gli sviluppatori le gestiscano manualmente, anziché introdurre altri tipi di dettagli di errore.

Ecco alcuni payload error_details di esempio:

  • ErrorInfo: fornisce informazioni sugli errori strutturati che sono sia stabili sia estendibili.
  • RetryInfo: descrive quando i client possono riprovare a effettuare una richiesta non riuscita, possono essere restituiti in data Code.UNAVAILABLE o Code.ABORTED
  • QuotaFailure: descrive in che modo un controllo della quota non è riuscito, potrebbe essere restituito il giorno Code.RESOURCE_EXHAUSTED
  • BadRequest: descrive le violazioni nella richiesta di un cliente, che possono essere restituite il giorno Code.INVALID_ARGUMENT

Informazioni sull'errore

ErrorInfo è un tipo speciale di payload di errore. Fornisce informazioni su errori stabili ed estensibili da cui esseri umani e applicazioni possono dipendere. Ogni ErrorInfo ha tre informazioni: un dominio di errore, un motivo dell'errore e una serie di metadati di errore, come questo esempio. Per ulteriori informazioni, consulta la definizione di ErrorInfo.

Per le API di Google, il dominio di errore principale è googleapis.com e i motivi di errore corrispondenti sono definiti da google.api.ErrorReason enum. Per ulteriori informazioni, consulta la definizione di google.api.ErrorReason.

Errore di localizzazione

Il campo message in google.rpc.Status è rivolto agli sviluppatori e deve essere in inglese.

Se è necessario un messaggio di errore visualizzato dall'utente, utilizza google.rpc.LocalizedMessage come campo dei dettagli. Anche se il campo del messaggio in google.rpc.LocalizedMessage può essere localizzato, assicurati che il campo del messaggio in google.rpc.Status sia in inglese.

Per impostazione predefinita, il servizio API deve utilizzare le impostazioni internazionali o l'intestazione HTTP Accept-Language dell'utente autenticato o il parametro language_code nella richiesta per determinare la lingua per la localizzazione.

Errore nella mappatura

Le API di Google sono accessibili in diversi ambienti di programmazione. In genere, ogni ambiente ha un proprio modo di gestire gli errori. Le seguenti sezioni spiegano come viene mappato il modello di errore negli ambienti di uso comune.

Mappatura HTTP

Mentre i messaggi proto3 hanno una codifica JSON nativa, la piattaforma API di Google utilizza uno schema di errore diverso per le API HTTP JSON di Google per motivi di compatibilità con le versioni precedenti.

Schema:

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

Esempio (link):

{
  "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"
        }
      }
    ]
  }
}

Mappatura gRPC

Diversi protocolli RPC mappano il modello di errore in modo diverso. Per gRPC, il modello di errore è supportato in modo nativo dal codice generato e dalla libreria di runtime in ogni linguaggio supportato. Per saperne di più, consulta la documentazione dell'API gRPC. Ad esempio, consulta la pagina Java di gRPC io.grpc.Status.

Mappatura della libreria client

Le librerie client di Google possono scegliere di mostrare errori diversi per lingua, in modo che siano coerenti con gli idiomi consolidati. Ad esempio, la libreria google-cloud-go restituirà un errore che implementa la stessa interfaccia di google.rpc.Status, mentre google-cloud-java genera un'eccezione.

Gestione degli errori

Di seguito è riportata una tabella contenente tutti i codici di errore gRPC definiti in google.rpc.Code e una breve descrizione della causa. Per gestire un errore, puoi controllare la descrizione del codice di stato restituito e modificare la chiamata di conseguenza.

HTTP gRPC Descrizione
200 OK Nessun errore.
400 INVALID_ARGUMENT Il client ha specificato un argomento non valido. Per ulteriori informazioni, controlla il messaggio e i dettagli dell'errore.
400 FAILED_PRECONDITION Non è possibile eseguire la richiesta nello stato di sistema attuale, ad esempio è necessario eliminare una directory non vuota.
400 OUT_OF_RANGE Il client ha specificato un intervallo non valido.
401 UNAUTHENTICATED La mancata autenticazione della richiesta è dovuta a un token OAuth mancante, non valido o scaduto.
403 PERMISSION_DENIED Il client non dispone di autorizzazioni sufficienti. Questo può accadere perché il token OAuth non dispone degli ambiti corretti, il client non dispone dell'autorizzazione o l'API non è stata abilitata.
404 NOT_FOUND Risorsa specificata non trovata.
409 ABORTED Conflitto di contemporaneità, ad esempio conflitto di lettura, modifica e scrittura.
409 ALREADY_EXISTS La risorsa che un client ha cercato di creare esiste già.
429 RESOURCE_EXHAUSTED Quota di risorse esaurita o vicina alla limitazione della frequenza. Per ulteriori informazioni, il client deve cercare i dettagli dell'errore google.rpc.QuotaFailure.
499 CANCELLED La richiesta è stata annullata dal client.
500 DATA_LOSS Perdita di dati non recuperabili o danneggiamento dei dati. Il client dovrebbe segnalare l'errore all'utente.
500 UNKNOWN Errore sconosciuto del server. In genere un bug del server.
500 INTERNAL Errore interno del server. In genere un bug del server.
501 NOT_IMPLEMENTED Metodo API non implementato dal server.
502 N/D Si è verificato un errore di rete prima di raggiungere il server. In genere un'interruzione di rete o una configurazione errata.
503 UNAVAILABLE Servizio non disponibile. In genere il server non è attivo.
504 DEADLINE_EXCEEDED Scadenza richiesta superata. Questo accade solo se il chiamante imposta una scadenza inferiore alla scadenza predefinita del metodo (ovvero la scadenza richiesta non è sufficiente per l'elaborazione della richiesta da parte del server) e la richiesta non è stata completata entro la scadenza.

Nuovo tentativo per risolvere errori

I client potrebbero ripetere l'operazione in caso di errori 503 NON DISPONIBILI con backoff esponenziale. Il ritardo minimo deve essere di 1 s, a meno che non sia diversamente documentato. La ripetizione del test predefinito dovrebbe essere una volta, a meno che non sia documentata diversamente.

Per gli errori 429 RESOURCE_EXHAUSTED, il client può riprovare al livello più alto, con un ritardo minimo di 30 secondi. Questi tentativi sono utili solo per i job in background a lunga esecuzione.

Per tutti gli altri errori, riprova, potrebbe non essere applicabile. Innanzitutto, assicurati che la tua richiesta sia idempotente e consulta la pagina google.rpc.RetryInfo per indicazioni.

Errori di propagazione

Se il servizio API dipende da altri servizi, non devi distribuire alla cieca gli errori dai servizi ai tuoi client. Quando traduci errori, ti suggeriamo di procedere come segue:

  • Nascondi i dettagli di implementazione e le informazioni riservate.
  • Modifica la parte responsabile dell'errore. Ad esempio, un server che riceve un errore INVALID_ARGUMENT da un altro servizio dovrebbe propagare un INTERNAL al proprio chiamante.

Riproduzione degli errori

Se non riesci a risolvere gli errori tramite l'analisi dei log e il monitoraggio, devi provare a riprodurre gli errori con un test semplice e ripetibile. Puoi utilizzare il test per raccogliere ulteriori informazioni per la risoluzione dei problemi, che puoi fornire quando contatti l'assistenza tecnica.

Ti consigliamo di utilizzare oauth2l, curl -v e parametri di sistema per riprodurre gli errori nelle API di Google. Insieme possono riprodurre quasi tutte le richieste API di Google e fornirti informazioni di debug dettagliate. Per ulteriori informazioni, consulta le pagine di documentazione relative all'API che stai chiamando.

Generazione degli errori

Se sei uno sviluppatore di server, dovresti generare errori con informazioni sufficienti per consentire agli sviluppatori dei client di comprendere e risolvere il problema. Allo stesso tempo, devi essere consapevole della sicurezza e della privacy dei dati utente ed evitare di divulgare informazioni sensibili nel messaggio di errore e nei dettagli dell'errore, poiché gli errori vengono spesso registrati e potrebbero essere accessibili ad altri. Ad esempio, un messaggio di errore come "L'indirizzo IP del client non è nella lista consentita 128.0.0.0/8" espone le informazioni sul criterio lato server, che potrebbero non essere accessibili all'utente che ha accesso ai log.

Per generare errori corretti, devi prima conoscere google.rpc.Code per scegliere il codice di errore più adatto per ogni condizione di errore. Un'applicazione server può controllare più condizioni di errore in parallelo e restituire la prima.

Nella tabella che segue sono elencati tutti i codici di errore e un esempio di messaggio di errore valido.

HTTP gRPC Esempio di messaggio di errore
400 INVALID_ARGUMENT Il campo di richiesta x.y.z è xxx, uno previsto di [yyy, zzz].
400 FAILED_PRECONDITION La risorsa xxx è una directory non vuota, quindi non può essere eliminata.
400 OUT_OF_RANGE Il parametro 'age' è fuori intervallo [0, 125].
401 UNAUTHENTICATED Credenziali di autenticazione non valide.
403 PERMISSION_DENIED Autorizzazione 'xxx' negata nella risorsa 'yyy'.
404 NOT_FOUND Risorsa 'xxx' non trovata.
409 ABORTED Impossibile acquisire il blocco nella risorsa 'xxx'.
409 ALREADY_EXISTS Risorsa 'xxx' esiste già.
429 RESOURCE_EXHAUSTED Limite quota 'xxx' superato.
499 CANCELLED La richiesta è stata annullata dal client.
500 DATA_LOSS Vedi la nota.
500 UNKNOWN Vedi la nota.
500 INTERNAL Vedi la nota.
501 NOT_IMPLEMENTED Metodo 'xxx' non implementato.
503 UNAVAILABLE Vedi la nota.
504 DEADLINE_EXCEEDED Vedi la nota.

Payload degli errori

Il pacchetto google.rpc definisce un insieme di payload di errore standard, preferiti ai payload di errore personalizzati. La tabella riportata di seguito elenca ogni codice di errore e il relativo payload di errore standard corrispondente, se applicabile. Consigliamo alle applicazioni avanzate di cercare questi payload di errore in google.rpc.Status quando gestiscono gli errori.

HTTP gRPC Dettagli errore consigliato
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