En este capítulo, se proporciona una descripción general del modelo de error para las APIs de Google. También brinda orientación general a los desarrolladores sobre cómo generar y para manejar los errores.
Las APIs de Google usan un modelo de error sencillo e independiente del protocolo, lo que nos permite Ofrecen una experiencia coherente en diferentes APIs y protocolos de API. (como gRPC o HTTP) y diferentes contextos de error (como los errores por lotes o de flujo de trabajo).
Modelo de error
El modelo de error de las APIs de Google se define de manera lógica por google.rpc.Status
, una instancia de la cual se muestra al cliente cuando se produce un error de API. En el siguiente fragmento de código, se muestra el diseño general del modelo de error:
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;
}
Debido a que la mayoría de las API de Google usan un diseño de API orientado a los recursos, el manejo de errores sigue el mismo principio de diseño, ya que usa un conjunto pequeño de errores estándar con una gran cantidad de recursos. Por ejemplo, en lugar de definir las diferentes clases de errores del tipo “no se encontró”, el servidor usa un código de error estándar google.rpc.Code.NOT_FOUND
y le comunica al cliente qué recurso no se encontró. El espacio de error más pequeño reduce la complejidad de la documentación, permite mejorar las asignaciones idiomáticas en las bibliotecas cliente y reduce la complejidad de la lógica de los clientes sin restringir la inclusión de información práctica.
Códigos de error
Las APIs de Google deben usar los códigos de error canónicos definidos por google.rpc.Code
.
Las APIs individuales deben evitar la definición de códigos de error adicionales, ya que es muy poco probable que los desarrolladores escriban lógica con el fin de manejar una gran cantidad de códigos de error. A modo de referencia, manejar un promedio de tres códigos de error por llamada a la API implica que la mayoría de la lógica de la aplicación se destine solo al manejo de errores, lo que no sería una buena experiencia para los desarrolladores.
Mensajes de error
El mensaje de error debe ayudar a los usuarios a comprender y resolver el error de la API de manera fácil y rápida. En general, ten en cuenta las siguientes pautas cuando escribas mensajes de error:
- No supongas que el usuario es un experto en tu API. Los usuarios pueden ser desarrolladores de clientes, personal de operaciones, personal de TI o usuarios finales de aplicaciones.
- No supongas que el usuario conoce la implementación del servicio o está familiarizado con el contexto de los errores (como el análisis de registros).
- Cuando sea posible, los mensajes de error se deben construir de manera tal que un usuario técnico (pero no necesariamente un desarrollador de tu API) pueda responder al error y corregirlo.
- Escribe un mensaje de error breve. Si es necesario, proporciona un vínculo en el que un lector que tenga dudas pueda hacer preguntas, hacer comentarios o recibir más información que no cabe de forma clara en un mensaje de error. De lo contrario, usa el campo de detalles para proporcionar más información.
Detalles de errores
Las API de Google definen un conjunto de cargas útiles de error estándar para los detalles de errores, que puedes encontrar en google/rpc/error_details.proto. Estas incluyen las necesidades más comunes de los errores de API, como las fallas de cuota y los parámetros no válidos. Al igual que los códigos de error, los desarrolladores deben usar estas cargas útiles estándar siempre que sea posible.
Los tipos de detalles de errores adicionales solo se deben ingresar si pueden ayudar al código de la aplicación a manejar los errores. Si solo las personas pueden manejar la información de errores, confía en el contenido del mensaje de error y permite que los desarrolladores lo manejen de forma manual en lugar de ingresar nuevos tipos de detalles de errores.
Estos son algunos ejemplos de cargas útiles de error_details
:
ErrorInfo
: Proporciona información de errores estructurada que es estable y extensible.RetryInfo
: Describe cuándo los clientes pueden volver a intentar una solicitud fallida, es posible que se muestre enCode.UNAVAILABLE
oCode.ABORTED
QuotaFailure
: Describe cómo falló una verificación de cuota, es posible que se muestre enCode.RESOURCE_EXHAUSTED
BadRequest
: Describe violaciones en una solicitud del cliente, puede mostrarse enCode.INVALID_ARGUMENT
Información de error
ErrorInfo
es un tipo especial de carga útil de error. Proporciona valores estables y
información de errores extensible de la que puedan depender las personas y las aplicaciones.
Cada ErrorInfo
tiene tres datos: un dominio de error, un error
y un conjunto de metadatos de error, como este
ejemplo.
Para obtener más información, consulta la
ErrorInfo
definición.
Para las APIs de Google, el dominio de error principal es googleapis.com
, y los motivos de error correspondientes se definen mediante la enumeración google.api.ErrorReason
.
Para obtener más información, consulta la
google.api.ErrorReason
definición.
Localización de errores
El campo message
en
google.rpc.Status
está orientado al desarrollador y debe estar en inglés.
Si se necesita un mensaje de error para el usuario, usa google.rpc.LocalizedMessage
como campo de detalles. Mientras el campo de mensaje
google.rpc.LocalizedMessage
puedan localizarse, asegúrate de que el campo del mensaje en
google.rpc.Status
está en inglés.
De forma predeterminada, el servicio de API debe usar la configuración regional del usuario autenticado o el encabezado HTTP Accept-Language
o el parámetro language_code
en la solicitud para determinar el idioma para la localización.
Asignación de errores
Se puede acceder a las APIs de Google en diferentes entornos de programación. Por lo general, cada entorno tiene su propia forma de controlar los errores. En las siguientes secciones, se explica cómo se asigna el modelo de error en entornos de uso general.
Asignación HTTP
Mientras que los mensajes proto3 tienen codificación JSON nativa, la plataforma de la API de Google usa un esquema de error diferente para las APIs de JSON HTTP de Google para retrocompatibilidad y otras razones.
Esquema
// 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;
}
Ejemplo (vínculo):
{
"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"
}
}
]
}
}
Asignación gRPC
Los diferentes protocolos de RPC asignan el modelo de error de manera diferente. Para gRPC, el modelo de error es compatible de forma nativa con el código generado y la biblioteca del entorno de ejecución en cada lenguaje admitido. Puedes obtener más información en la documentación de la API de gRPC. Por ejemplo, consulta io.grpc.Status
de gRPC para Java.
Asignación de bibliotecas cliente
Las bibliotecas cliente de Google pueden optar por mostrar errores de manera diferente en cada lenguaje para que sean coherentes con los idiomas establecidos. Por ejemplo, la biblioteca google-cloud-go mostrará un error que implementa la misma interfaz que google.rpc.Status
, mientras que google-cloud-java generará una excepción.
Maneja los errores
A continuación, se muestra una tabla que contiene todos los códigos de error de gRPC definidos en
google.rpc.Code
y una breve descripción de su causa. Para manejar un error, puedes verificar la descripción del código de estado que se muestra y modificar tu llamada según corresponda.
HTTP | gRPC | Descripción |
---|---|---|
200 | OK |
No hay errores. |
400 | INVALID_ARGUMENT |
El cliente especificó un argumento no válido. Verifica el mensaje de error y los detalles de errores para obtener más información. |
400 | FAILED_PRECONDITION |
La solicitud no se puede ejecutar en el estado actual del sistema, como borrar un directorio que no esté vacío. |
400 | OUT_OF_RANGE |
El cliente especificó un rango no válido. |
401 | UNAUTHENTICATED |
La solicitud no se autenticó debido a que el token de OAuth no es válido, falta o se venció. |
403 | PERMISSION_DENIED |
El cliente no cuenta con los permisos necesarios. Esto puede suceder porque el token de OAuth no tiene los alcances correctos, el cliente no tiene permiso o la API no se habilitó. |
404 | NOT_FOUND |
No se encontró ningún recurso especificado. |
409 | ABORTED |
Conflicto de simultaneidad, como conflicto del proceso de lectura, modificación y escritura. |
409 | ALREADY_EXISTS |
El recurso que el cliente intentó crear ya existe. |
429 | RESOURCE_EXHAUSTED |
Sin cuota de recursos o a punto de alcanzar el límite de frecuencia. Para obtener más información, el cliente debe buscar el detalle de error google.rpc.QuotaFailure. |
499 | CANCELLED |
El cliente canceló la solicitud. |
500 | DATA_LOSS |
Daño o pérdida de datos no recuperable. El cliente debe informar el error al usuario. |
500 | UNKNOWN |
Error de servidor desconocido. Por lo general, un error de servidor. |
500 | INTERNAL |
Error del servidor interno Por lo general, un error de servidor. |
501 | NOT_IMPLEMENTED |
El servidor no implementó el método de API. |
502 | N/A | Se produjo un error de red antes de acceder al servidor. Por lo general, se trata de una interrupción de la red o una configuración incorrecta. |
503 | UNAVAILABLE |
Servicio no disponible. Por lo general, el servidor no está en funcionamiento. |
504 | DEADLINE_EXCEEDED |
Se excedió el plazo de la solicitud. Esto ocurrirá solo si el emisor establece una fecha límite más corta que la fecha límite predeterminada del método (es decir, la fecha límite solicitada no es suficiente para que el servidor procese la solicitud) y la solicitud no finalizó dentro de la fecha límite. |
Reintentos de errores
Los clientes pueden volver a intentar errores 503 UNAVAILABLE con retirada exponencial. El retraso mínimo debe ser de 1 s, a menos que se documente lo contrario. La repetición predeterminada del reintento debe ser una vez, a menos que se documente lo contrario.
En el caso de los errores 429 RESOURCE_EXHAUSTED, el cliente puede reintentar en el nivel superior con un retraso mínimo de 30 s. Esos reintentos solo son útiles en casos de uso trabajos en segundo plano.
Para todos los demás errores, es posible que el reintento no sea aplicable. Primero, asegúrate de que tu solicitud sea idempotente y consulta google.rpc.RetryInfo
para obtener orientación.
Propagación de errores
Si tu servicio de API depende de otros servicios, no debes propagar los errores de esos servicios a tus clientes. Cuando se traducen errores, sugerimos lo siguiente:
- Oculta los detalles de implementación y la información confidencial.
- Configura la parte responsable del error. Por ejemplo, un servidor que recibe un error
INVALID_ARGUMENT
de otro servicio debe propagar unINTERNAL
a su propio emisor.
Cómo reproducir errores
Si no puedes resolver los errores mediante el análisis de registros y la supervisión, debes intentar reproducirlos con una prueba simple y repetible. Puedes usar la a fin de recopilar más información para solucionar problemas, que puedes proporcionar cuando te comuniques con el equipo de asistencia técnica.
Te recomendamos que uses curl -v
y Parámetros del sistema para reproducir errores con las APIs de Google. Juntos pueden reproducir casi todas las solicitudes a las APIs de Google,
y brindarte información de depuración detallada. Para obtener más información, consulta las
páginas de documentación correspondientes de la API a la que llamas.
Genera errores
Si eres un desarrollador de servidores, debes generar errores con información suficiente para ayudar a los desarrolladores cliente a comprender y resolver el problema. Al mismo tiempo, debes conocer la seguridad y la privacidad de los datos del usuario y evitar revelar información sensible en el mensaje y los detalles del error, ya que los errores a menudo se registran y otros pueden acceder a ellos. Por ejemplo, un mensaje de error como “La dirección IP de cliente no está en la lista de entidades permitidas 128.0.0.0/8” muestra información sobre la política del lado del servidor, que puede no ser accesible para el usuario que tiene acceso a los registros.
Para generar los errores adecuados, primero debes estar familiarizado con google.rpc.Code
para
elegir el código de error más adecuado para cada condición de error. Una aplicación del servidor puede verificar varias condiciones de error en paralelo y mostrar la primera.
En la siguiente tabla, se enumera cada código de error y un ejemplo de un mensaje de error correcto.
HTTP | gRPC | Ejemplo de mensaje de error |
---|---|---|
400 | INVALID_ARGUMENT |
El campo de solicitud x.y.z es xxx, se esperaba uno de [yyy, zzz]. |
400 | FAILED_PRECONDITION |
El recurso xxx no es un directorio vacío, por lo que no se puede borrar. |
400 | OUT_OF_RANGE |
El parámetro “edad” está fuera del rango [0, 125]. |
401 | UNAUTHENTICATED |
Credenciales de autenticación no válidas. |
403 | PERMISSION_DENIED |
Permiso “xxx” denegado en el archivo “yyy”. |
404 | NOT_FOUND |
No se encontró el recurso “xxx”. |
409 | ABORTED |
No se pudo aplicar el bloqueo en el recurso “xxx”. |
409 | ALREADY_EXISTS |
El recurso “xxx” ya existe. |
429 | RESOURCE_EXHAUSTED |
Se excedió el límite de cuota “xxx”. |
499 | CANCELLED |
El cliente canceló la solicitud. |
500 | DATA_LOSS |
Consulta la nota. |
500 | UNKNOWN |
Consulta la nota. |
500 | INTERNAL |
Consulta la nota. |
501 | NOT_IMPLEMENTED |
No se implementó el método “xxx”. |
503 | UNAVAILABLE |
Consulta la nota. |
504 | DEADLINE_EXCEEDED |
Consulta la nota. |
Cargas útiles de error
El paquete google.rpc
define un conjunto de carga útil de error estándar, que se prefieren a las cargas útiles de error personalizadas. En la siguiente tabla, se enumera cada código de error y su carga útil de error estándar coincidente, si corresponde. Recomendamos las opciones avanzadas
las aplicaciones buscarán estas cargas útiles de error en google.rpc.Status
cuando
para manejar los errores.
HTTP | gRPC | Detalle de error recomendado |
---|---|---|
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 |