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](https://google.aip.dev/193) standard
for error details, providing machine-readable information that allows your
application to handle specific error scenarios programmatically.

> [!NOTE]
> **Note:** This error response structure is being rolled out gradually across Merchant API. Only errors returned by the Products, Reports and Data sources sub-APIs follow the format described here. Errors from other sub-APIs might still be in a legacy format and might not include the `ErrorInfo` metadata.

## 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]
> **Note:** If `internal_error` persists after multiple retries with backoff, see [How to contact Merchant API support](https://developers.google.com/merchant/api/guides/error-handling#how-to-contact-api-support).

## How to contact Merchant API support

If you need to contact [Merchant API support](https://developers.google.com/merchant/api/support/get-help)
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