Información sobre los errores de la API

En esta guía, se explica cómo la API de Data Manager controla y comunica los errores. Comprender la estructura y el significado de los errores de la API es fundamental para compilar aplicaciones sólidas que puedan controlar los problemas de forma correcta, desde entradas no válidas hasta la falta de disponibilidad temporal del servicio.

La API de Data Manager sigue el modelo de error estándar de la API de Google, que se basa en los códigos de estado de gRPC. Cada respuesta de la API que genera un error incluye un objeto Status con lo siguiente:

  • Un código de error numérico.
  • Es un mensaje de error.
  • Detalles adicionales del error (opcional).

Códigos de error canónicos

La API de Data Manager usa un conjunto de códigos de error canónicos definidos por gRPC y HTTP. Estos códigos proporcionan una indicación de alto nivel del tipo de error. Siempre debes verificar este código primero para comprender la naturaleza fundamental del problema.

Para obtener más detalles sobre estos códigos, consulta la Guía de diseño de APIs: Códigos de error.

Modelo de falla rápida

La API de Data Manager usa un modelo de falla rápida. Si una solicitud contiene errores estructurales o si algún registro no supera la validación de un campo obligatorio, toda la solicitud falla y la API no procesa ninguno de los datos de esa solicitud.

Comparación con el modelo de falla parcial

El modelo de falla rápida difiere del modelo de falla parcial en algunas otras APIs de Google, como la API de Google Ads y la API de Campaign Manager 360. En el modelo de falla parcial, una solicitud se completa correctamente incluso si algunos registros tienen errores, y la respuesta contiene detalles del error para los registros con errores.

Aunque la falla parcial puede ser conveniente, conlleva riesgos significativos, ya que el modelo de falla parcial no te alerta de forma proactiva sobre los errores, sino que debes verificar de forma explícita si hay errores en cada respuesta. Esto puede ocultar problemas importantes, ya que una solicitud se realiza correctamente incluso si la API rechaza muchos o incluso todos los registros de la solicitud. Si una parte significativa de los registros de una solicitud tiene errores, pero no inspeccionas la respuesta, es posible que no te enteres de los problemas generalizados con tus datos y que solo los descubras días o semanas después, cuando los resultados acumulados no se alineen con tus expectativas.

El modelo de falla rápida evita estos problemas, ya que te alerta sobre problemas con tus datos o la integración de inmediato para que puedas tomar las medidas adecuadas.

Verifica si hay errores de falla rápida con validateOnly

La mayoría de las solicitudes de transferencia y eliminación admiten un campo validateOnly. Cuando estableces validateOnly en true, la API de Data Manager ejecuta las mismas verificaciones de validación básicas que para una solicitud normal, pero no transfiere ni quita ningún dato.

  • Si la solicitud tiene errores, falla con la misma respuesta de error que obtendrías de una solicitud normal.
  • Si la solicitud pasa la validación, se realiza correctamente. La respuesta incluye cualquier fieldWarnings para los campos opcionales, como una solicitud normal.

Utiliza validateOnly para:

  • Prueba una integración nueva o actualizada sin afectar tus datos en tiempo real.
  • Confirma que la corrección resuelva el error antes de volver a enviar la solicitud.

Soluciona errores

Sigue estos pasos cuando falle una solicitud:

  1. Verifica el código de error para encontrar el tipo de error.

    • Si usas gRPC, el código de error se encuentra en el campo code de Status. Si usas una biblioteca cliente, es posible que arroje un tipo específico de excepción que corresponda al código de error. Por ejemplo, la biblioteca cliente para Java arroja una com.google.api.gax.rpc.InvalidArgumentException si el código de error es INVALID_ARGUMENT.
    • Si usas REST, el código de error se encuentra en la respuesta de error en error.status, y el estado HTTP correspondiente se encuentra en error.code.
  2. Verifica la carga útil de detalles estándar para ver el código de error. Las cargas útiles de detalles estándar son un conjunto de mensajes para errores de las APIs de Google. Te brindan detalles de los errores de una manera estructurada y coherente. Cada error de la API de Data Manager puede tener varios mensajes de carga útil de detalles estándar. Las bibliotecas cliente de la API de Data Manager tienen métodos auxiliares para obtener las cargas útiles de detalles estándar de un error.

    Independientemente del código de error, te recomendamos que verifiques y registres las cargas útiles de ErrorInfo, RequestInfo, Help y LocalizedMessage.

    • ErrorInfo tiene información que podría no estar en otras cargas útiles.
    • RequestInfo tiene el ID de la solicitud, que es útil si necesitas comunicarte con el equipo de asistencia.
    • Help y LocalizedMessage contienen vínculos y otros detalles para ayudarte a solucionar el error.

    Además, la carga útil de BadRequest es útil para los errores de INVALID_ARGUMENT, ya que proporciona información sobre qué campos causaron el error.

Advertencias de transferencia

La API de Data Manager acepta la mayor cantidad posible de solicitudes de transferencia. Si incluyes datos que no son obligatorios, los errores de validación de esos campos no harán que la solicitud falle. Por ejemplo, si a un artículo del carrito le falta un ID del producto del comercio, la API procesa el resto de la solicitud y devuelve una advertencia.

Una respuesta de transferencia correcta (código de estado HTTP 200) incluye estas advertencias en una lista fieldWarnings. Cada entrada es un objeto FieldWarning con los siguientes campos:

field

Es la ubicación del campo en la solicitud, en la sintaxis de la ruta de acceso en minúsculas con guiones bajos.

Si una ruta de acceso apunta a un elemento de una lista (un campo repeated), su índice se muestra entre corchetes ([...]) después del nombre de la lista.

Por ejemplo, events.events[0].cart_data.items[0].merchant_product_id identifica una advertencia relacionada con el primer artículo de los datos del carrito del primer evento de la solicitud.

description

Es una explicación de por qué el valor proporcionado causó una advertencia.

reason

Es el valor de la enumeración WarningReason que identifica el tipo de advertencia.

Ejemplo con FieldWarning

A continuación, se muestra una respuesta de ejemplo para una solicitud de transferencia correcta que contiene una advertencia porque faltaba un ID del producto del comercio para uno de los artículos del carrito.

{
  "requestId": "126365e1-16d0-4c81-9de9-f362711e250a",
  "fieldWarnings": [
    {
      "field": "events.events[0].cart_data.items[0].merchant_product_id",
      "description": "The merchant product ID is missing in the cart item.",
      "reason": "WARNING_REASON_CART_DATA_ITEM_MERCHANT_PRODUCT_ID_MISSING"
    }
  ]
}

Cargas útiles de detalles estándar

Estas son las cargas útiles de detalles estándar más comunes para la API de Data Manager:

BadRequest

Verifica la carga útil BadRequest cuando una solicitud falla con INVALID_ARGUMENT (código de estado HTTP 400).

Un mensaje BadRequest indica que la solicitud tenía campos con valores incorrectos o que faltaba un valor para un campo obligatorio. Consulta la lista field_violations en el BadRequest para saber qué campos tienen errores. Cada entrada de field_violations tiene información para ayudarte a corregir el error:

field

Es la ubicación del campo en la solicitud, en la sintaxis de ruta de acceso de minúsculas con guiones bajos.

Si una ruta de acceso apunta a un elemento de una lista (un campo repeated), su índice se muestra entre corchetes ([...]) después del nombre de la lista.

Por ejemplo, destinations[0].operating_account.account_id es el account_id en el operating_account del primer elemento de la lista destinations.

description

Una explicación de por qué el valor causó un error.

reason

Es la enumeración ErrorReason, como INVALID_HEX_ENCODING o INVALID_CURRENCY_CODE.

Ejemplos de BadRequest

Esta es una respuesta de ejemplo para un error INVALID_ARGUMENT con un mensaje BadRequest. El field_violations muestra que el error es un accountId que no es un número. El valor destinations[0].login_account.account_id de field muestra que el accountId con un incumplimiento de campo se encuentra en el login_account del primer elemento de la 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"
          }
        ]
      }
    ]
  }
}

Aquí tienes otra respuesta de ejemplo de un error INVALID_ARGUMENT con un mensaje BadRequest. En este caso, la lista field_violations muestra dos errores:

  1. El primer event tiene un valor que no está codificado en formato hexadecimal en el segundo identificador de usuario del evento.

  2. El segundo event tiene un valor que no está codificado en formato hexadecimal en el tercer identificador de usuario del 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"
          }
        ]
      }
    ]
  }
}

RequestInfo

Verifica la carga útil de RequestInfo cada vez que falle una solicitud. Un RequestInfo contiene el request_id que identifica de forma única tu solicitud a la API.

{
  "@type": "type.googleapis.com/google.rpc.RequestInfo",
  "requestId": "t-4490c640-dc5d-4c28-91c1-04a1cae0f49f"
}

Cuando registres errores o te comuniques con el equipo de asistencia, asegúrate de incluir el ID de la solicitud para ayudar a diagnosticar los problemas.

ErrorInfo

Verifica el mensaje ErrorInfo para recuperar información adicional que tal vez no se capture en las otras cargas útiles de detalles estándar. La carga útil de ErrorInfo contiene un mapa de metadata con información sobre el error.

Por ejemplo, aquí se muestra el ErrorInfo de una falla de PERMISSION_DENIED causada por el uso de credenciales para un proyecto de Google Cloud en el que no está habilitada la API de Data Manager. El ErrorInfo proporciona información adicional sobre el error, como la siguiente:

  • Es el proyecto asociado con la solicitud, en metadata.consumer.
  • El nombre del servicio, en metadata.serviceTitle.
  • Es la URL en la que se puede habilitar el servicio, en 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.cloud.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.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
        }
      },
      ...
    ]
  }
}

Errores de cuota y límite de frecuencia

Cuando una solicitud supera un límite del proyecto, la API devuelve un error RESOURCE_EXHAUSTED (código de estado HTTP 429). La carga útil ErrorInfo proporciona detalles sobre qué límite se superó en su mapa metadata:

consumer
Es el proyecto de Google Cloud asociado a la solicitud, con el formato projects/PROJECT_NUMBER.
quota_limit
Es el nombre del límite de cuota que se excedió, como IngestionMutateRequestsPerMinutePerProject o IngestionMutateRequestsPerDayPerProject. Puedes usar este valor para determinar si la aplicación superó un límite por minuto o un límite diario. Para obtener la lista completa de los nombres de los límites, consulta Límites del proyecto.
quota_location
Es la ubicación en la que se aplica la cuota. Para la API de Data Manager, siempre es global.
quota_metric
Es la métrica asociada con el límite, como datamanager.googleapis.com/ingestion_mutate_requests.
service
El nombre del servicio, datamanager.googleapis.com.

Este es un ejemplo de una respuesta de error RESOURCE_EXHAUSTED cuando una solicitud supera el límite por minuto de solicitudes de mutación de transferencia:

{
  "error": {
    "code": 429,
    "message": "Quota exceeded for quota metric 'Ingestion mutate requests' and limit 'Ingestion mutate requests per minute' of service 'datamanager.googleapis.com' for consumer 'project_number:PROJECT_NUMBER'.",
    "status": "RESOURCE_EXHAUSTED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "RATE_LIMIT_EXCEEDED",
        "domain": "googleapis.com",
        "metadata": {
          "consumer": "projects/PROJECT_NUMBER",
          "quota_limit": "IngestionMutateRequestsPerMinutePerProject",
          "quota_location": "global",
          "quota_metric": "datamanager.googleapis.com/ingestion_mutate_requests",
          "service": "datamanager.googleapis.com"
        }
      }
    ]
  }
}

Help y LocalizedMessage

Verifica las cargas útiles Help y LocalizedMessage para obtener vínculos a la documentación y los mensajes de error localizados que te ayuden a comprender y corregir el error.

Por ejemplo, aquí se muestran el Help y el LocalizedMessage de un error PERMISSION_DENIED causado por el uso de credenciales para un proyecto de Google Cloud en el que la API de Data Manager no está habilitada. La carga útil de Help muestra la URL en la que se puede habilitar el servicio, y LocalizedMessage tiene una descripción del error.

{
  "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.cloud.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.cloud.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 API Console API activation",
            "url": "https://console.cloud.google.com/apis/api/datamanager.googleapis.com/overview?project=PROJECT_NUMBER"
          }
        ]
      },
      ...
    ]
  }
}

Detalles del error de acceso

Si usas una de las bibliotecas cliente, utiliza los métodos auxiliares para obtener las cargas útiles de detalles estándar.

.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.ErrorInfo)
        {
            Google.Rpc.ErrorInfo errorInfo = (Google.Rpc.ErrorInfo)detail;
            // Log the errorInfo.Reason and errorInfo.Metadata...

            // If handling a rate limit error, check the exceeded quota limit:
            if (errorInfo.Reason == "RATE_LIMIT_EXCEEDED" &&
                errorInfo.Metadata.TryGetValue("quota_limit", out string quotaLimit))
            {
                // Inspect quotaLimit to determine whether it is a per-minute
                // or daily limit (for example,
                // IngestionMutateRequestsPerMinutePerProject).
            }

            // Log the details in the 'Metadata' map...
            foreach (
                KeyValuePair<String, String> metadataEntry in errorInfo.Metadata
            )
            {
                // Log the metadataEntry.Key and metadataEntry.Value...
            }
        }
        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.ApiException apiException) {
  // Fallback exception handler for other types of ApiException.

  // Gets the standard ErrorInfo payload from the exception.
  ErrorInfo errorInfo = apiException.getErrorDetails().getErrorInfo();
  // Log the 'reason' and 'domain'...

  // If handling a rate limit error, check the exceeded quota limit:
  if (errorInfo != null && "RATE_LIMIT_EXCEEDED".equals(errorInfo.getReason())) {
    String quotaLimit = errorInfo.getMetadataMap().get("quota_limit");
    // Inspect quotaLimit to determine whether it is a per-minute
    // or daily limit (for example,
    // IngestionMutateRequestsPerMinutePerProject).
  }

  // Log the details in the 'metadata' map...
  for (Entry<String, String> metadataEntry : errorInfo.getMetadataMap().entrySet()) {
    // Log the metadataEntry key and value...
  }

  // Gets the standard RequestInfo payload from the exception.
  RequestInfo requestInfo = apiException.getErrorDetails().getRequestInfo();
  if (requestInfo != null) {
    String requestId = requestInfo.getRequestId();
    // Log the requestId...
  }
  ...
}

Controla los errores de tamaño de encabezado para gRPC

Cuando una gran cantidad de registros en una solicitud de transferencia o eliminación no pasa la validación, la API de Data Manager devuelve todos los errores en la carga útil BadRequest de la respuesta.

En gRPC, el servicio devuelve estos detalles del error en los encabezados de respuesta HTTP/2 (metadatos). De forma predeterminada, las bibliotecas cliente de gRPC limitan los encabezados entrantes a un tamaño máximo (por lo general, de 8 a 10 KB). Si los detalles del error superan este límite, el transporte HTTP/2 del cliente falla antes de analizar la respuesta de error y arroja una excepción como la siguiente:

Http2Exception: Header size exceeded max allowed size (10240)

Debido a que el cliente no puede procesar los encabezados de respuesta, cancela la transmisión (que aparece como estado HTTP 499 Client Closed Request en los registros del servidor) y tu aplicación no puede acceder a los detalles del error BadRequest.

Para resolver este problema y, también, inspeccionar la lista completa de errores, configura tu cliente de gRPC con un tamaño máximo de metadatos entrantes mayor (como 16 MB):

.NET

// Creates a client for the ingestion service. Increases the maximum metadata size to
// 16MB to prevent RESOURCE_EXHAUSTED errors when responses contain large error
// details.
IngestionServiceClient ingestionServiceClient = new IngestionServiceClientBuilder
{
    GrpcChannelOptions = GrpcChannelOptions.Empty.WithCustomOption(
        "grpc.max_metadata_size",
        16 * 1024 * 1024
    ),
}.Build();

Java

// Creates a client for the ingestion service. Increases the maximum metadata size to 16MB to
// prevent RESOURCE_EXHAUSTED errors when responses contain large error details.
InstantiatingGrpcChannelProvider provider =
    IngestionServiceSettings.defaultGrpcTransportProviderBuilder()
        .setMaxInboundMetadataSize(16 * 1024 * 1024)
        .build();
IngestionServiceSettings settings =
    IngestionServiceSettings.newBuilder().setTransportChannelProvider(provider).build();
try (IngestionServiceClient ingestionServiceClient = IngestionServiceClient.create(settings)) {
  // ...
}

Nodo

// Creates a client for the ingestion service. Increases the maximum metadata
// size to 16MB to prevent RESOURCE_EXHAUSTED errors when responses contain
// large error details.
const client = new IngestionServiceClient({
  'grpc.max_metadata_size': 16 * 1024 * 1024,
});

PHP

// Creates a client for the ingestion service. Increases the maximum metadata size to 16MB to
// prevent RESOURCE_EXHAUSTED errors when responses contain large error details.
$client = new IngestionServiceClient([
    'transportConfig' => [
        'grpc' => [
            'stubOpts' => [
                'grpc.max_metadata_size' => 16 * 1024 * 1024,
            ],
        ],
    ],
]);

Python

# Creates a client for the ingestion service. Increases the maximum
# metadata size to 16MB to prevent RESOURCE_EXHAUSTED errors when responses
# contain large error details.
channel = datamanager_v1.services.ingestion_service.transports.IngestionServiceGrpcTransport.create_channel(
    options=[("grpc.max_metadata_size", 16 * 1024 * 1024)]
)
transport = datamanager_v1.services.ingestion_service.transports.IngestionServiceGrpcTransport(
    channel=channel
)
client: datamanager_v1.IngestionServiceClient = (
    datamanager_v1.IngestionServiceClient(transport=transport)
)

Prácticas recomendadas para el manejo de errores

Para compilar aplicaciones resilientes, implementa las siguientes prácticas recomendadas.

Valida antes de enviar
Cuando crees o cambies una integración, envía solicitudes con validateOnly establecido en true para detectar errores de falla rápida antes de transferir datos.
Inspecciona los detalles del error
Siempre busca una de las cargas útiles de detalles estándar, como BadRequest. Cada carga útil de detalles estándar contiene información que te ayuda a comprender la causa del error.
Diferencia los errores del cliente de los errores de servidor

Determina si el error se debe a un problema con tu implementación (el cliente) o con la API (el servidor).

  • Errores del cliente: Códigos como INVALID_ARGUMENT, NOT_FOUND, PERMISSION_DENIED, FAILED_PRECONDITION, UNAUTHENTICATED. Estos requieren cambios en la solicitud o en el estado o las credenciales de tu aplicación. No vuelvas a intentar la solicitud sin abordar el problema.
  • Errores de servidor: Códigos como UNAVAILABLE, INTERNAL, DEADLINE_EXCEEDED, UNKNOWN. Esto sugiere un problema temporal con el servicio de la API.
Implementa una estrategia de reintento

Determina si se puede reintentar el error y usa una estrategia de reintento.

  • Vuelve a intentarlo solo para errores de servidor transitorios (como UNAVAILABLE, DEADLINE_EXCEEDED, INTERNAL, UNKNOWN y ABORTED) y límites de frecuencia por minuto (RESOURCE_EXHAUSTED con RATE_LIMIT_EXCEEDED).

  • Para conocer los límites de frecuencia, inspecciona el quota_limit en ErrorInfo:

    • Si el límite es por minuto (como IngestionMutateRequestsPerMinutePerProject), pausa las solicitudes y vuelve a intentarlo con una retirada exponencial con Jitter.

    • Si el límite es diario (como IngestionMutateRequestsPerDayPerProject), no vuelvas a intentarlo de inmediato. Pausar el procesamiento hasta que se restablezca la cuota diaria a la medianoche, hora del Pacífico.

  • Usa un algoritmo de retirada exponencial para esperar períodos cada vez más largos entre los reintentos. Esto ayuda a evitar que se sobrecargue un servicio que ya está saturado. Por ejemplo, espera 1 s, luego 2 s, luego 4 s, y continúa hasta alcanzar una cantidad máxima de reintentos o un tiempo de espera total.

  • Agrega una pequeña cantidad aleatoria de "fluctuación" a los retrasos de retirada para evitar el problema de "activación simultánea" en el que muchos clientes vuelven a intentarlo simultáneamente.

Registra con detalle

Registra la respuesta de error completa, incluidas todas las cargas útiles de detalles estándar, en especial el ID de solicitud. Esta información es esencial para depurar y, si es necesario, informar problemas al equipo de Atención al cliente de Google.

Proporciona comentarios de los usuarios

Según los códigos y los mensajes de las cargas útiles de detalles estándar, proporciona comentarios claros y útiles a los usuarios de tu aplicación. Por ejemplo, en lugar de solo "Se produjo un error", puedes decir "Falta el ID de transacción" o "No se encontró el ID de cuenta del destino".

Si sigues estos lineamientos, podrás diagnosticar y controlar de manera eficaz los errores que devuelve la API de Data Manager, lo que generará aplicaciones más estables y fáciles de usar.