Handle error responses

This guide explains how to handle errors returned by the Merchant API. Understanding the error response structure and stability is crucial for building robust integrations that can automatically recover from failures or provide meaningful feedback to users.

Overview

When a Merchant API request fails, the API returns a standard HTTP status code (4xx or 5xx) and a JSON response body containing details about the error. The Merchant API follows the AIP-193 standard for error details, providing machine-readable information that allows your application to handle specific error scenarios programmatically.

Error response structure

The error response is a JSON object that contains standard fields like code, message, and status. Crucially, it also includes a details array. To handle errors programmatically, you should look for an object within details where the @type is type.googleapis.com/google.rpc.ErrorInfo.

This ErrorInfo object provides stable, structured data about the error:

  • domain: The logical grouping of the error, typically merchantapi.googleapis.com.
  • metadata: A map of dynamic values related to the error. This includes:
    • REASON: A specific, stable identifier for the exact error (e.g., INVALID_NAME_PART_NOT_NUMBER, PERMISSION_DENIED_ACCOUNTS). This field is always present. Use this field for fine grained error handling in your application logic.
    • HELP_CENTER_LINK: Provides additional context and instructions to fix the issue. This field is not present for all errors, but we plan to expand its coverage over time for the errors where more context might be needed.
    • Other dynamic fields: Other keys providing context, such as the name of the invalid field (FIELD_LOCATION) or the value that caused the error (FIELD_VALUE).

Sample error responses

The following JSON demonstrates the structure of a Merchant API error where a resource name was malformed.

{
  "error": {
    "code": 400,
    "message": "[name] The part `account` of the resource name in field `name` must be a number, but has value: `abcd`.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "invalid",
        "domain": "merchantapi.googleapis.com",
        "metadata": {
          "VARIABLE_NAME": "account",
          "FIELD_LOCATION": "name",
          "FIELD_VALUE": "abcd",
          "REASON": "INVALID_NAME_PART_NOT_NUMBER"
        }
      }
    ]
  }
}

Here is an example of an authentication error:

{
  "error": {
    "code": 401,
    "message": "The caller does not have access to the accounts: [1234567]",
    "status": "UNAUTHENTICATED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "unauthorized",
        "domain": "merchantapi.googleapis.com",
        "metadata": {
          "ACCOUNT_IDS": "[1234567]",
          "REASON": "PERMISSION_DENIED_ACCOUNTS"
        }
      }
    ]
  }
}

Stability of error fields

When writing error handling logic, it is important to know which fields are safe to rely on and which might change.

  • Stable fields:
  • details.metadata.REASON: The specific error identifier. You should rely on this field for your application's control flow logic.

    • details.metadata keys: The keys within the metadata map (e.g., FIELD_LOCATION, ACCOUNT_IDS) are stable.
    • code: The high-level HTTP status code (e.g., 400, 401, 503) is stable.
  • Unstable fields:

    • message: The human-readable error message is not stable. It is intended for developer debugging only. Do not write code that parses or relies on the text content of the message field, as it may change without notice to improve clarity or add context.
    • details.metadata values: While the keys are stable, the values for informational keys may change. For example, if a HELP_CENTER_LINK key is provided, the specific URL it points to might be updated to a newer documentation page without prior notification. However, as mentioned earlier, the value of details.metadata.REASON is stable.

Best practices

Follow these best practices to ensure your integration handles errors gracefully.

Use details.metadata.REASON for logic

Always use the specific REASON inside the metadata map to determine the cause of an error. Don't rely on the HTTP status code alone, as multiple errors may share the same status code.

Don't parse the error message

As noted in the stability section, the message field is for human consumption. If you need dynamic information (like which field was invalid), extract it from the metadata map using stable keys like FIELD_LOCATION, VARIABLE_NAME.

Implement exponential backoff

For errors indicating temporary unavailability or rate limiting, implement an exponential backoff strategy. This means waiting for a short period before retrying, and increasing the wait time with each subsequent failure.

  • quota/request_rate_too_high: This error indicates you have exceeded your minute quota for specific quota group. Slow down your request rate.
  • internal_error: These are usually transient. Retry with exponential backoff. Note: If internal_error persists after multiple retries with backoff, see How to contact Merchant API support.

How to contact Merchant API support

If you need to contact Merchant API support about a specific error, provide the following information in your request:

  1. The exact error response received
  2. The API method name
  3. The request payload
  4. Timestamps or the time range during which the method was called and errors were received