Erros

Neste capítulo, apresentamos uma visão geral do modelo de erro das APIs do Google e orientações comuns aos desenvolvedores sobre como gerar e lidar corretamente com erros.

As APIs do Google usam um modelo simples de erro independente de protocolo, que nos permite expor uma experiência consistente em diferentes APIs, protocolos de APIs, como gRPC ou HTTP, e contextos de erro (para erros de instância, assíncronos, de lote ou de fluxo de trabalho).

Modelo de erro

O modelo de erro é definido logicamente por google.rpc.Status, uma instância retornada ao cliente quando ocorre um erro na API. O snippet de código a seguir mostra o projeto geral do modelo de erro:

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

Como a maioria das APIs do Google usa um design orientado a recursos, o tratamento de erros segue o mesmo princípio do design, usando um pequeno conjunto de erros padrão com uma grande quantidade de recursos. Por exemplo, em vez de definir diferentes tipos de erros "não encontrado", um código de erro padrão google.rpc.Code.NOT_FOUND é usado pelo servidor e informa ao cliente qual recurso específico não foi encontrado. O espaço com estado menor reduz a complexidade da documentação, oferece melhores mapeamentos idiomáticos nas bibliotecas de cliente e reduz a complexidade da lógica do cliente sem restringir a inclusão de informações acionáveis.

Códigos dos erros

Nas APIs do Google, é preciso usar os códigos de erro canônicos definidos por google.rpc.Code. As APIs individuais devem evitar a definição de códigos dos erros adicionais, porque é muito improvável que os desenvolvedores escrevam uma lógica para lidar com um grande número de códigos dos erros. Para referência, o tratamento de uma média de três códigos de erro por chamada de API significa que a maior parte da lógica do aplicativo é apenas para o tratamento de erros, o que não é uma boa experiência para o desenvolvedor.

Mensagens de erro

A mensagem de erro deve ajudar os usuários a entender e resolver o erro da API de maneira fácil e rápida. Em geral, considere as diretrizes a seguir ao escrever mensagens de erro:

  • Não presuma que os usuários sejam especialistas na sua API. Eles podem ser desenvolvedores de clientes, pessoal de operações, equipe de TI ou usuários finais de aplicativos.
  • Não presuma que o usuário saiba de tudo sobre a implementação do seu serviço ou esteja familiarizado com o contexto dos erros (como análise de registro).
  • Quando possível, as mensagens de erro precisam ser criadas de maneira que um usuário técnico, não necessariamente um desenvolvedor da sua API, possa responder ao erro e corrigi-lo.
  • Mantenha a mensagem de erro resumida. Se necessário, forneça um link em que um leitor com dúvidas possa fazer perguntas, dar feedback ou obter mais informações que não se encaixam em uma mensagem de erro. Caso contrário, use o campo de detalhes para expandir.

Detalhes do erro

As APIs do Google definem um conjunto de payloads de erro padrão para detalhes de erros, que você pode encontrar em google/rpc/error_details.proto. Eles abrangem as necessidades mais comuns de erros de API, como falha de cota e parâmetros inválidos. Como os códigos dos erros, os detalhes usarão esses payloads padrão sempre que possível.

Os tipos de detalhes de erros adicionais apenas serão introduzidos se puderem ajudar o código do aplicativo a lidar com os erros. Se as informações de erro exigirem interação humana, confie no conteúdo da mensagem de erro e deixe os desenvolvedores lidarem com isso manualmente, em vez de introduzir novos tipos de detalhes de erros.

Veja a seguir alguns exemplos de payloads error_details:

  • RetryInfo informa quando os clientes podem repetir uma solicitação com falha. Pode ser retornado em Code.UNAVAILABLE ou Code.ABORTED
  • QuotaFailure descreve como uma verificação de cota falhou. Pode ser retornado em Code.RESOURCE_EXHAUSTED
  • BadRequest descreve violações em uma solicitação do cliente. Pode ser retornado em Code.INVALID_ARGUMENT

Mapeamento de HTTP

Enquanto as mensagens proto3 têm codificação JSON nativa, a plataforma da API do Google usa um esquema de erros diferente para as APIs Google JSON REST por motivos de compatibilidade com versões anteriores.

Esquema:

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

Por exemplo:

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

Mapeamento de RPC

Cada protocolo RPC mapeia o modelo de erro de maneira diferente. Para gRPC, o modelo de erro é compatível de maneira nativa com o código gerado e com a biblioteca de tempo de execução em cada linguagem aceita. Veja mais informações na documentação da API gRPC. Por exemplo, consulte io.grpc.Status do gRPC em Java.

Mapeamento da biblioteca de cliente

As bibliotecas de cliente do Google podem exibir erros de modo diferente, conforme a linguagem, para consistência com idiomas estabelecidos. Por exemplo, na biblioteca google-cloud-go, é retornado um erro que implementa a mesma interface de google.rpc.Status, enquanto em google-cloud-java é gerada uma exceção.

Localização de erros

O campo message em google.rpc.Status é voltado para o desenvolvedor e precisa estar em inglês.

Se for preciso enviar uma mensagem de erro para o usuário, use google.rpc.LocalizedMessage como o campo de detalhes. O campo de mensagem em google.rpc.LocalizedMessage pode ser localizado, mas o campo de mensagem em google.rpc.Status precisa estar em inglês.

Por padrão, o serviço da API deve usar a localidade do usuário autenticado ou o cabeçalho HTTP Accept-Language para determinar a linguagem de localização.

Como lidar com erros

Veja abaixo uma tabela com todos os códigos de erro do gRPC definidos em google.rpc.Code e uma breve descrição da causa. Para lidar com um erro, você pode verificar a descrição do código de status retornado e modificar a chamada de acordo com ela.

HTTP RPC Descrição
200 OK Sem erro.
400 INVALID_ARGUMENT O cliente especificou um argumento inválido. Verifique a mensagem e os detalhes do erro para mais informações.
400 FAILED_PRECONDITION A solicitação não pode ser executada no estado atual do sistema atual, como excluir um diretório que não está vazio.
400 OUT_OF_RANGE O cliente especificou um intervalo inválido.
401 UNAUTHENTICATED Solicitação não autenticada devido ao token OAuth ausente, inválido ou expirado.
403 PERMISSION_DENIED O cliente não tem permissão suficiente. Isso pode acontecer porque o token OAuth não tem os escopos certos, o cliente não tem permissão ou a API não foi ativada para o projeto do cliente.
404 NOT_FOUND Um recurso especificado não foi encontrado ou a solicitação foi rejeitada por motivos não divulgados, como a listagem de permissões.
409 ABORTED Conflito de simultaneidade, como leitura-modificação-gravação.
409 ALREADY_EXISTS O recurso que um cliente tentou criar já existe.
429 RESOURCE_EXHAUSTED Fora da cota de recursos ou perto de atingir o limite de taxa. O cliente deve buscar os detalhes do erro em "google.rpc.QuotaFailure" para mais informações.
499 CANCELLED Solicitação cancelada pelo cliente.
500 DATA_LOSS Perda de dados irrecuperável ou dados corrompidos. O cliente deve comunicar o erro ao usuário.
500 UNKNOWN Erro desconhecido no servidor. Geralmente, um bug do servidor.
500 INTERNAL Erro interno do servidor. Geralmente, um bug do servidor.
501 NOT_IMPLEMENTED Método da API não implementado pelo servidor.
503 UNAVAILABLE Serviço indisponível. Geralmente, o servidor está desativado.
504 DEADLINE_EXCEEDED O prazo de solicitação foi excedido. Isso acontecerá somente se o chamador definir um prazo menor que o prazo padrão do método (ou seja, o prazo solicitado não é suficiente para o servidor processar a solicitação) e a solicitação não for concluída dentro do prazo.

Novas tentativas em caso de erro

Os clientes devem tentar novamente no caso dos erros 500 e 503 com retorno exponencial. O atraso mínimo deve ser de um segundo, a menos que seja documentado de outra maneira. Para os erros 429, o cliente pode tentar novamente com um atraso mínimo de 30 segundos. Para todos os outros erros, a nova tentativa pode não ser aplicável. Primeiro, verifique se a solicitação é idempotente e veja a mensagem de erro para orientação.

Propagação de erro

Se o serviço da API depende de outros serviços, não convém propagar precipitadamente os erros desses serviços para os seus clientes. Ao traduzir erros, sugerimos o seguinte:

  • Oculte detalhes de implementação e informações confidenciais.
  • Ajuste a parte responsável pelo erro. Por exemplo, um servidor que recebe um erro INVALID_ARGUMENT de outro serviço deve propagar um INTERNAL para o próprio autor da chamada.

Como gerar erros

Se você é um desenvolvedor de servidores, precisa gerar erros com informações suficientes para ajudar os desenvolvedores de clientes a entender e resolver o problema. Ao mesmo tempo, você precisa estar ciente da segurança e da privacidade dos dados do usuário e evitar a divulgação de informações confidenciais na mensagem e nos detalhes do erro, visto que os erros geralmente são registrados e podem ser acessados por outras pessoas. Por exemplo, uma mensagem de erro como "O endereço IP do cliente não está na lista de permissões 128.0.0.0/8" expõe informações sobre a política do servidor, o que talvez não seja acessível ao usuário.

Para gerar os erros da forma correta, primeiro é preciso estar familiarizado com o google.rpc.Code para escolher o código mais adequado em cada condição. Um aplicativo do servidor pode verificar várias condições de erro em paralelo e retornar a primeira.

A tabela a seguir lista cada código do erro e um exemplo de uma boa mensagem.

HTTP RPC Exemplo de mensagem de erro
400 INVALID_ARGUMENT O campo de solicitação xyz é xxx, mas o esperado é [yyy, zzz].
400 FAILED_PRECONDITION O recurso xxx é um diretório que não está vazio, portanto, não pode ser excluído.
400 OUT_OF_RANGE A "idade" do parâmetro está fora do intervalo [0, 125].
401 UNAUTHENTICATED Credenciais de autenticação inválidas.
403 PERMISSION_DENIED Permissão "xxx" negada no arquivo "yyy".
404 NOT_FOUND O recurso "xxx" não foi encontrado.
409 ABORTED Não foi possível adquirir o bloqueio no recurso "xxx".
409 ALREADY_EXISTS O recurso "xxx" já existe.
429 RESOURCE_EXHAUSTED Limite de cota "xxx" excedido.
499 CANCELLED Solicitação cancelada pelo cliente.
500 DATA_LOSS Consulte a observação.
500 UNKNOWN Consulte a observação.
500 INTERNAL Consulte a observação.
501 NOT_IMPLEMENTED Método "xxx" não implementado.
503 UNAVAILABLE Consulte a observação.
504 DEADLINE_EXCEEDED Consulte a observação.

OBSERVAÇÃO: já que o cliente não pode corrigir o erro do servidor, não é útil gerar detalhes de erro adicionais. Para evitar o vazamento de informações confidenciais em condições de erro, recomenda-se não gerar nenhuma mensagem, apenas os detalhes de erro de google.rpc.DebugInfo. O DebugInfo foi projetado especialmente para a geração de registro no servidor e não pode ser enviado ao cliente.

O pacote google.rpc define um conjunto de payloads de erro padrão, que tem preferência em relação aos payloads de erros personalizados. A tabela a seguir lista cada código do erro e o payload padrão correspondente, se aplicável.

HTTP RPC Detalhe de erro recomendado
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
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…