This document identifies the different types of errors that the API can return.

There are a few specific error codes need to be handled with custom logic. Error response encoded in the following format:

    {
      "error": {
        "code": 400,
        "message": "The user is already subscribed",
        "status": "FAILED_PRECONDITION",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.ErrorInfo",
            "reason": "ERROR_CODE_SUBSCRIPTION_REJECTED_ALREADY_SUBSCRIBED",
          }
        ]
      }
    }

## Generic Error Codes

| Error Code | Description | Client Action |
|---|---|---|
| UNAUTHORIZED (401) | The server cannot verify that you are authorized to access the resource. | Typically indicates that the provided access token is either invalid, expired, or missing, or that the client is not authorized to access the requested resource |
| NOT_FOUND (404) | The server cannot find a referenced resource in the request. | Confirm if any identifiers in the request is incorrect |

## Retriable HTTP Error Codes

The following http error codes indicate the system is temporarily unavailable, retrying with [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) is recommended.

| Error Code | Description | Client Action |
|---|---|---|
| 409 | Requested resource state conflict | Retry using exponential backoff |
| 429 | Requests are throttled | Retry using exponential backoff |
| 503 | Service is temporarily unavailable | Retry using exponential backoff |
| 504 | Server timed out | Retry using exponential backoff |

## Custom Error Code

Custom error code is encoded in ErrorInfo.reason, as in the example above. The possible errors for each API is specified as follows:

### partners.subscriptions.create

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_REJECTED_ALREADY_SUBSCRIBED | FAILED_PRECONDITION (400) | End user is already subscribed with Google | Consider guiding the user to cancel the subscription on the appropriate Google site first |
| ERROR_CODE_SUBSCRIPTION_REJECTED_SUBSCRIPTION_INELIGIBLE | FAILED_PRECONDITION (400) | End user is ineligible for the subscription | The subscription cannot be activated for the user |
| ERROR_CODE_SUBSCRIPTION_REJECTED_PROMOTION_INELIGIBLE | FAILED_PRECONDITION (400) | End user is ineligible for the promotion | Consider removing the promotion or using another one |
| ERROR_CODE_SUBSCRIPTION_REJECTED_RATIONALE_OTHER | FAILED_PRECONDITION (400) | The subscription is rejected and no more detailed rationale is available at this moment | Please double check that the subscription is valid |
| ERROR_CODE_SUBSCRIPTION_ALREADY_CANCELLED | FAILED_PRECONDITION (400) | The subscription to upgrade or downgrade is already cancelled. | Do not retry, cancelled subscription cannot be upgraded or downgraded. |
| ERROR_CODE_SUBSCRIPTION_USER_MISMATCH | FAILED_PRECONDITION (400) | The user's Google Account or partner_user_token in the subscription doesn't match the existing record for upgrade and downgrade. | Do not retry with the same Google Account or partner_user_token |
| ERROR_CODE_SUBSCRIPTION_DETAILS_MISMATCH | FAILED_PRECONDITION (400) | The subscription details don't match the existing record for upgrade and downgrade, such as region code, billing frequency, etc. | Do not retry |
| ERROR_CODE_PRODUCT_NOT_FOUND | NOT_FOUND (404) | The product isn't found, isn't accessible by the partner, or isn't available in the requested service location | A different product or service location must be used |
| ERROR_CODE_PROMOTION_NOT_FOUND | NOT_FOUND (404) | The promotion isn't found, isn't accessible by the partner, or isn't available in the requested service location | A different promotion or service location must be used |
| ERROR_CODE_SUBSCRIPTION_NOT_FOUND | NOT_FOUND (404) | The subscription to upgrade or downgrade isn't found | A different subscription must be used |
| ERROR_CODE_SUBSCRIPTION_IN_REQUESTED_STATE | ALREADY_EXISTS (409) | The subscription is already in the request state. | A different subscription id must be used. Do not retry. |

### partners.subscriptions.provision

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_REJECTED_ALREADY_SUBSCRIBED | FAILED_PRECONDITION (400) | End user is already subscribed with Google | Consider guiding the user to cancel the subscription on the appropriate Google site first |
| ERROR_CODE_SUBSCRIPTION_REJECTED_SUBSCRIPTION_INELIGIBLE | FAILED_PRECONDITION (400) | End user is ineligible for the subscription | The subscription cannot be activated for the user |
| ERROR_CODE_SUBSCRIPTION_REJECTED_PROMOTION_INELIGIBLE | FAILED_PRECONDITION (400) | End user is ineligible for the promotion | Consider removing the promotion or using another one |
| ERROR_CODE_SUBSCRIPTION_REJECTED_RATIONALE_OTHER | FAILED_PRECONDITION (400) | The subscription is rejected and no more detailed rationale is available at this moment | Please double check that the subscription is valid |
| ERROR_CODE_PRODUCT_NOT_FOUND | FAILED_PRECONDITION (400) | The product isn't found, isn't accessible by the partner, or isn't available in the requested service location | A different product or service location must be used |
| ERROR_CODE_PROMOTION_NOT_FOUND | FAILED_PRECONDITION (400) | The promotion isn't found, isn't accessible by the partner, or isn't available in the requested service location | A different promotion or service location must be used |
| ERROR_CODE_SUBSCRIPTION_USER_MISMATCH | FAILED_PRECONDITION (400) | The user info in the subscription doesn't match the existing record for upgrade and downgrade | Do not retry with the same partner_user_token |
| ERROR_CODE_SUBSCRIPTION_DETAILS_MISMATCH | FAILED_PRECONDITION (400) | The subscription details don't match the existing record for upgrade and downgrade | Do not retry |
| ERROR_CODE_SUBSCRIPTION_NOT_FOUND | NOT_FOUND (404) | The subscription to upgrade or downgrade isn't found | A different subscription must be used |
| ERROR_CODE_SUBSCRIPTION_IN_REQUESTED_STATE | ALREADY_EXISTS (409) | The subscription is already in the request state. | A different subscription id must be used. Do not retry. |

### partners.subscriptions.entitle

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_REJECTED_ALREADY_SUBSCRIBED | FAILED_PRECONDITION (400) | End user is already subscribed with Google via another subscription | Consider guiding the user to cancel the subscription on the appropriate Google site first |
| ERROR_CODE_SUBSCRIPTION_ALREADY_ENTITLED | FAILED_PRECONDITION (400) | The subscription is already entitled to the end user in the request | Do not retry |
| ERROR_CODE_SUBSCRIPTION_ALREADY_ENTITLED_TO_ANOTHER_USER | FAILED_PRECONDITION (400) | The subscription is already entitled to a different user than the one in the request | Do not retry |
| ERROR_CODE_SUBSCRIPTION_REJECTED_SUBSCRIPTION_INELIGIBLE | FAILED_PRECONDITION (400) | End user is ineligible for the subscription | The subscription cannot be activated for the user |
| ERROR_CODE_SUBSCRIPTION_REJECTED_PROMOTION_INELIGIBLE | FAILED_PRECONDITION (400) | End user is ineligible for the promotion | Consider canceling the subscription. |
| ERROR_CODE_SUBSCRIPTION_REJECTED_RATIONALE_OTHER | FAILED_PRECONDITION (400) | The subscription is rejected and no more detailed rationale is available at this moment | Please double check that the subscription is valid |

### partners.subscriptions.extend

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_ALREADY_CANCELLED | FAILED_PRECONDITION (400) | The subscription is already cancelled. | Do not retry |
| ERROR_CODE_SUBSCRIPTION_IS_PROCESSING_REQUEST | FAILED_PRECONDITION (400) | The subscription is already being processed for the requested operation | Do not retry |
| ERROR_CODE_SUBSCRIPTION_IN_REQUESTED_STATE | FAILED_PRECONDITION (400) | The requested operation is already complete | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_STATE | FAILED_PRECONDITION (400) | Subscription is in a state that is not valid for the requested operation | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_PROCESSING_STATE | FAILED_PRECONDITION (400) | Subscription is in progress of another request and not valid for the requested operation | The request could be retried |
| ERROR_CODE_REQUEST_ID_COLLISION | FAILED_PRECONDITION (400) | Request with the same request_id has already been processed | Do not retry |
| ERROR_CODE_SUBSCRIPTION_NOT_FOUND | NOT_FOUND (404) | The subscription to extend isn't found | A different subscription must be used |

### partners.subscriptions.cancel

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_ALREADY_CANCELLED | FAILED_PRECONDITION (400) | Subscription is already cancelled | Do not retry |
| ERROR_CODE_SUBSCRIPTION_IS_PROCESSING_REQUEST | FAILED_PRECONDITION (400) | The subscription is already being processed for the requested operation | Do not retry |
| ERROR_CODE_SUBSCRIPTION_IN_REQUESTED_STATE | FAILED_PRECONDITION (400) | The requested operation is already complete | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_STATE | FAILED_PRECONDITION (400) | Subscription is in a state that is not valid for the requested operation | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_PROCESSING_STATE | FAILED_PRECONDITION (400) | Subscription is in progress of another request and not valid for the requested operation | The request could be retried |
| ERROR_CODE_SUBSCRIPTION_NOT_FOUND | NOT_FOUND (404) | The subscription to cancel isn't found | A different subscription must be used |

### partners.subscriptions.undoCancel

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_IS_PROCESSING_REQUEST | FAILED_PRECONDITION (400) | The subscription is already being processed for the requested operation | do not retry |
| ERROR_CODE_SUBSCRIPTION_IN_REQUESTED_STATE | FAILED_PRECONDITION (400) | The requested operation is already complete | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_STATE | FAILED_PRECONDITION (400) | Subscription is already cancelled and cannot be undone | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_PROCESSING_STATE | FAILED_PRECONDITION (400) | Subscription is in progress of another request and not valid for the requested operation. | The request could be retried |
| ERROR_CODE_SUBSCRIPTION_ALREADY_CANCELLED | FAILED_PRECONDITION (400) | The subscription is already cancelled and undo cancel cannot be done. | Do not retry |

### partners.subscriptions.resume

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_IN_REQUESTED_STATE | FAILED_PRECONDITION (400) | The requested operation is already complete | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_STATE | FAILED_PRECONDITION (400) | Subscription is already cancelled and cannot be undone | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_PROCESSING_STATE | FAILED_PRECONDITION (400) | Subscription is in progress of another request and not valid for the requested operation. | The request could be retried |

### partners.subscriptions.suspend

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_IN_REQUESTED_STATE | FAILED_PRECONDITION (400) | The requested operation is already complete | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_STATE | FAILED_PRECONDITION (400) | Subscription is already cancelled and cannot be undone | Do not retry |
| ERROR_CODE_SUBSCRIPTION_BAD_PROCESSING_STATE | FAILED_PRECONDITION (400) | Subscription is in progress of another request and not valid for the requested operation. | The request could be retried |

### partners.subscriptions.get

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| ERROR_CODE_SUBSCRIPTION_NOT_FOUND | NOT_FOUND (404) | The subscription to get isn't found | A different subscription must be used |

### partners.subscriptions.lineItems.patch

| Error Reason | Error type | Description | Client Action |
|---|---|---|---|
| - | INVALID_ARGUMENT (400) | An invalid update mask can result in this error (e.g. contains fields that are not allowed to be updated). The error message would contain additional information. | Fix the update mask in the request as per the error message. |
| - | NOT_FOUND (404) | The line item provided in the request is not found. | Confirm if any identifiers in the request is incorrect. |
| ERROR_CODE_SUBSCRIPTION_REJECTED_RATIONALE_OTHER | FAILED_PRECONDITION (400) | The subscription is rejected for updating line items and no more detailed rationale is available at this moment | Do not retry |

### partners.promotions.findEligible

| Error type | Description | Client Action |
|---|---|---|
| FAILED_PRECONDITION (400) | An invalid filter can result in this error. In this case, error message would contain additional information about the case. | Fix the filter in the request as per the error message. |

### partners.userSessions.generate

| Error type | Description | Client Action |
|---|---|---|
| INVALID_ARGUMENT (400) | Unsupported intent payload. | Fix the intent payload with supported intent type |
| INVALID_ARGUMENT (400) | Provision API should be used for upgrade/downgrade in managed activation flow. | Do not retry. |

## Java example

You can extract the custom error code from the ErrorInfo as follows:

    try {
      client
        .partners()
        .subscriptions()
        .entitle("partners/partnerId/subscriptions/subscriptionId",
            new GoogleCloudPaymentsResellerSubscriptionV1EntitleSubscriptionRequest())
        .setAccessToken(credential.getAccessToken())
        // It is important to overwrite the parameter: &.xgafv=2.
        // Otherwise, the legacy API mode is used by default, where error details
        // are trimmed off for compatibility.
        .set$Xgafv("2");
        .execute();
    } catch (GoogleJsonResponseException e) {
        // process error reason by decoding e.getDetails().
      }