Este guia explica como a API Central de dados processa e comunica erros. Entender a estrutura e o significado dos erros de API é fundamental para criar aplicativos robustos que podem lidar com problemas, desde entradas inválidas até indisponibilidade temporária do serviço.
A API Central de dados segue o modelo de erro padrão das APIs do Google, que se baseia em códigos de status do gRPC. Cada resposta da API que resulta em um
erro inclui um objeto Status com:
- Um código do erro numérico.
- Uma mensagem de erro.
- Opcional, outros detalhes do erro.
Códigos de erro canônicos
A API Central de dados usa um conjunto de códigos de erro canônicos definidos por gRPC e HTTP. Esses códigos fornecem uma indicação geral do tipo de erro. Sempre verifique esse código primeiro para entender a natureza fundamental do problema.
Para mais detalhes sobre esses códigos, consulte o Guia de design de API - Códigos de erro.
Solucionar erros
Siga estas etapas quando uma solicitação falhar:
Verifique o código do erro para encontrar o tipo de erro.
- Se você usar o gRPC, o código do erro estará no campo
codedoStatus. Se você usar uma biblioteca de cliente, ela poderá gerar um tipo específico de exceção que corresponde ao código do erro. Por exemplo, a biblioteca de cliente para Java gera umcom.google.api.gax.rpc.InvalidArgumentExceptionse o código do erro forINVALID_ARGUMENT. - Se você usa REST, o código do erro está na resposta de erro em
error.status, e o status HTTP correspondente está emerror.code.
- Se você usar o gRPC, o código do erro estará no campo
Verifique a carga útil de detalhes padrão do código do erro. Os payloads de detalhes padrão são um conjunto de mensagens para erros das APIs do Google. Eles fornecem detalhes do erro de maneira estruturada e consistente. Cada erro da API Central de dados pode ter várias mensagens de payload de detalhes padrão. As bibliotecas de cliente da API Central de dados têm métodos auxiliares para receber os payloads de detalhes padrão de um erro.
Não importa o código do erro, recomendamos que você verifique e registre os payloads
ErrorInfo,RequestInfo,HelpeLocalizedMessage.ErrorInfotem informações que podem não estar em outros payloads.RequestInfotem o ID da solicitação, que é útil se você precisar entrar em contato com o suporte.HelpeLocalizedMessagecontêm links e outros detalhes para ajudar você a resolver o erro.
Além disso, os payloads
BadRequest,QuotaFailureeRetryInfosão úteis para códigos de erro específicos:- Se o código de status for
INVALID_ARGUMENT, verifique o payloadBadRequestpara saber quais campos causaram o erro. - Se o código de status for
RESOURCE_EXHAUSTED, verifique os payloadsQuotaFailureeRetryInfopara informações de cota e uma recomendação de atraso para nova tentativa.
Payloads de detalhes padrão
Os payloads de detalhes padrão mais comuns para a API Central de dados são:
BadRequest
Verifique o payload BadRequest quando uma solicitação falhar com
INVALID_ARGUMENT (código de status HTTP 400).
Uma mensagem BadRequest mostra que a solicitação tinha campos com valores incorretos ou não tinha um valor para um campo obrigatório. Verifique a lista field_violations no
BadRequest para saber quais campos têm erros. Cada entrada de field_violations
tem informações para ajudar você a corrigir o erro:
fieldO local do campo na solicitação, usando uma sintaxe de caminho de letras concatenadas.
Se um caminho apontar para um item em uma lista (um campo
repeated), o índice dele será mostrado entre colchetes ([...]) após o nome da lista.Por exemplo,
destinations[0].operating_account.account_idé oaccount_idnooperating_accountdo primeiro item na listadestinations.descriptionUma explicação de por que o valor causou um erro.
reasonO tipo enumerado
ErrorReason, comoINVALID_HEX_ENCODINGouINVALID_CURRENCY_CODE.
Exemplos de BadRequest
Confira um exemplo de resposta para um erro INVALID_ARGUMENT com uma mensagem BadRequest. O field_violations mostra que o erro é um accountId que não é um número. O valor destinations[0].login_account.account_id de field mostra que o
accountId com uma violação de campo está no login_account do primeiro item
na lista destinations.
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com",
"metadata": {
"requestId": "t-a8896317-069f-4198-afed-182a3872a660"
}
},
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-a8896317-069f-4198-afed-182a3872a660"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "destinations[0].login_account.account_id",
"description": "String is not a valid number.",
"reason": "INVALID_NUMBER_FORMAT"
}
]
}
]
}
}
Confira outro exemplo de resposta de um erro INVALID_ARGUMENT com uma mensagem BadRequest. Nesse caso, a lista field_violations mostra dois
erros:
O primeiro
eventtem um valor que não é codificado em hexadecimal no segundo identificador de usuário do evento.O segundo
eventtem um valor que não é codificado em hexadecimal no terceiro identificador de usuário do evento.
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com",
"metadata": {
"requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
}
},
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-6bc8fb83-d648-4942-9c49-2604276638d8"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "events.events[0].user_data.user_identifiers[1]",
"description": "The HEX encoded value is malformed.",
"reason": "INVALID_HEX_ENCODING"
},
{
"field": "events.events[1].user_data.user_identifiers[2]",
"description": "The HEX encoded value is malformed.",
"reason": "INVALID_HEX_ENCODING"
}
]
}
]
}
}
QuotaFailure e RetryInfo
Verifique os payloads QuotaFailure e RetryInfo quando uma solicitação falhar
com RESOURCE_EXHAUSTED (código de status HTTP 429).
Uma mensagem QuotaFailure indica que um recurso foi esgotado (por exemplo, você excedeu sua cota) ou que um sistema está sobrecarregado. Inspecione a lista de violations para determinar quais cotas foram excedidas.
O erro também pode conter uma mensagem RetryInfo, que indica um retry_delay recomendado para repetir a solicitação.
RequestInfo
Verifique o payload RequestInfo sempre que uma solicitação falhar. Um RequestInfo
contém o request_id que identifica exclusivamente sua solicitação de API.
{
"@type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}
Ao registrar erros ou entrar em contato com o suporte, inclua o ID da solicitação para ajudar no diagnóstico de problemas.
ErrorInfo
Verifique a mensagem ErrorInfo para recuperar informações adicionais que
podem não ser capturadas nos outros payloads de detalhes padrão. O payload ErrorInfo
contém um mapa metadata com informações sobre o erro.
Por exemplo, aqui está o ErrorInfo de uma falha PERMISSION_DENIED causada pelo uso de credenciais de um projeto na nuvem do Google em que a API Central de dados não está ativada. O ErrorInfo fornece mais informações sobre o erro, como:
- O projeto associado à solicitação, em
metadata.consumer. - O nome do serviço, em
metadata.serviceTitle. - O URL em que o serviço pode ser ativado, em
metadata.activationUrl.
{
"error": {
"code": 403,
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "SERVICE_DISABLED",
"domain": "googleapis.com",
"metadata": {
"consumer": "projects/PROJECT_NUMBER",
"service": "datamanager.googleapis.com",
"containerInfo": "PROJECT_NUMBER",
"serviceTitle": "Data Manager API",
"activationUrl": "https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
}
},
...
]
}
}
Help e LocalizedMessage
Verifique os payloads Help e LocalizedMessage para receber links da documentação e mensagens de erro localizadas que ajudam a entender e corrigir o erro.
Por exemplo, aqui estão Help e LocalizedMessage para uma falha de PERMISSION_DENIED causada pelo uso de credenciais de um projeto na nuvem do Google em que a API Central de dados não está ativada. O payload Help mostra o URL em que o serviço pode ser ativado, e o LocalizedMessage tem uma descrição do erro.
{
"error": {
"code": 403,
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.LocalizedMessage",
"locale": "en-US",
"message": "Data Manager API has not been used in project PROJECT_NUMBER before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
},
{
"@type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developers console API activation",
"url": "https://console.developers.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
}
]
},
...
]
}
}
Acessar detalhes do erro
Se você estiver usando uma das bibliotecas de cliente, use os métodos auxiliares para receber os payloads de detalhes padrão.
.NET
try {
// Send API request
}
catch (Grpc.Core.RpcException rpcException)
{
Console.WriteLine($"Exception encountered: {rpcException.Message}");
var statusDetails =
Google.Api.Gax.Grpc.RpcExceptionExtensions.GetAllStatusDetails(
rpcException
);
foreach (var detail in statusDetails)
{
if (detail is Google.Rpc.BadRequest)
{
Google.Rpc.BadRequest badRequest = (Google.Rpc.BadRequest)detail;
foreach (
BadRequest.Types.FieldViolation? fieldViolation in badRequest.FieldViolations
)
{
// Access attributes such as fieldViolation!.Reason and fieldViolation!.Field
}
}
else if (detail is Google.Rpc.RequestInfo)
{
Google.Rpc.RequestInfo requestInfo = (Google.Rpc.RequestInfo)detail;
string requestId = requestInfo.RequestId;
// Log the requestId...
}
else if (detail is Google.Rpc.QuotaFailure)
{
Google.Rpc.QuotaFailure quotaFailure = (Google.Rpc.QuotaFailure)detail;
foreach (
Google.Rpc.QuotaFailure.Types.Violation violation in quotaFailure.Violations
)
{
// Access attributes such as violation.Subject and violation.QuotaId
}
}
else
{
// ...
}
}
}
Java
try {
// Send API request
} catch (com.google.api.gax.rpc.InvalidArgumentException invalidArgumentException) {
// Gets the standard BadRequest payload from the exception.
BadRequest badRequest = invalidArgumentException.getErrorDetails().getBadRequest();
for (int i = 0; i < badRequest.getFieldViolationsCount(); i++) {
FieldViolation fieldViolation = badRequest.getFieldViolations(i);
// Access attributes such as fieldViolation.getField() and fieldViolation.getReason()
}
// Gets the standard RequestInfo payload from the exception.
RequestInfo requestInfo = invalidArgumentException.getErrorDetails().getRequestInfo();
if (requestInfo != null) {
String requestId = requestInfo.getRequestId();
// Log the requestId...
}
} catch (com.google.api.gax.rpc.QuotaFailureException quotaFailureException) {
// Gets the standard QuotaFailure payload from the exception.
QuotaFailure quotaFailure = quotaFailureException.getErrorDetails().getQuotaFailure();
for (int i = 0; i < quotaFailure.getViolationsCount(); i++) {
QuotaFailure.Violation violation = quotaFailure.getViolations(i);
// Access attributes such as violation.getSubject() and violation.getQuotaId()
}
// Gets the standard RequestInfo payload from the exception.
RequestInfo requestInfo = quotaFailureException.getErrorDetails().getRequestInfo();
if (requestInfo != null) {
String requestId = requestInfo.getRequestId();
// Log the requestId...
}
} catch (com.google.api.gax.rpc.ApiException apiException) {
// Fallback exception handler for other types of ApiException.
...
}
Práticas recomendadas para tratamento de erros
Para criar aplicativos resilientes, implemente as seguintes práticas recomendadas.
- Inspecionar detalhes do erro
- Sempre procure um dos payloads de detalhes
padrão, como
BadRequest. Cada payload de detalhes padrão contém informações para ajudar você a entender a causa do erro. - Diferenciar erros do cliente e do servidor
Determine se o erro é causado por um problema na sua implementação (o cliente) ou na API (o servidor).
- Erros do cliente: códigos como
INVALID_ARGUMENT,NOT_FOUND,PERMISSION_DENIED,FAILED_PRECONDITION,UNAUTHENTICATED. Esses exigem mudanças na solicitação ou no estado/credenciais do aplicativo. Não tente novamente sem resolver o problema. - Erros do servidor: códigos como
UNAVAILABLE,INTERNAL,DEADLINE_EXCEEDED,UNKNOWN. Isso sugere um problema temporário com o serviço de API.
- Erros do cliente: códigos como
- Implementar uma estratégia de repetição
Determine se o erro pode ser repetido e use uma estratégia de repetição.
- Tente de novo apenas para erros de servidor temporários, como
UNAVAILABLE,DEADLINE_EXCEEDED,INTERNAL,UNKNOWNeABORTED. - Use um algoritmo de espera exponencial para aguardar períodos cada vez maiores entre novas tentativas. Isso ajuda a evitar sobrecarregar um serviço já estressado. Por exemplo, aguarde 1 segundo, depois 2 segundos, depois 4 segundos e continue até um número máximo de novas tentativas ou tempo total de espera.
- Adicione uma pequena quantidade aleatória de "jitter" aos atrasos de espera para evitar o problema de "excesso de acionamentos", em que muitos clientes tentam novamente simultaneamente.
- Tente de novo apenas para erros de servidor temporários, como
- Registrar tudo
Registre a resposta de erro completa, incluindo todos os payloads de detalhes padrão, especialmente o ID da solicitação. Essas informações são essenciais para depurar e informar problemas ao suporte do Google, se necessário.
- Enviar feedback do usuário
Com base nos códigos e mensagens nos payloads de detalhes padrão, forneça feedback claro e útil aos usuários do seu aplicativo. Por exemplo, em vez de apenas "Ocorreu um erro", você pode dizer "O ID da transação estava faltando" ou "Não foi possível encontrar o ID da conta de destino".
Ao seguir essas diretrizes, você pode diagnosticar e processar erros retornados pela API Central de dados de maneira eficaz, resultando em aplicativos mais estáveis e fáceis de usar.