---
title: "What does paymentPendingError (code 20) mean in the purchases SDK?"
description: "paymentPendingError (code 20) means the purchase started but is not paid yet: Ask to Buy approval, a bank check or a delayed Google Play payment. It is not a failure."
url: https://revenuedot.app/docs/errors/sdk-payment-pending-error
---

# What does paymentPendingError (code 20) mean in the purchases SDK?

The purchases SDK raises paymentPendingError (code 20) when a purchase is pending and not yet paid.

## Quick facts

| | |
|---|---|
| Error | `ErrorCode.paymentPendingError` (iOS), `PurchasesErrorCode.PaymentPendingError` (Android), code 20 |
| Where | Purchases SDK (iOS, Android and the hybrid SDKs built on them) |
| What the vendor says | The payment is pending. |

## Cause

- StoreKit 2: the purchase result is `.pending`, which Apple describes as a purchase that requires action from the customer.
- StoreKit 1: a transaction in the `deferred` state, for example Ask to Buy.
- Android: the Play purchase state is `PENDING`. Google says to grant the entitlement only when the state is `PURCHASED`.

## Fix

1. Show a pending message such as "Your purchase is waiting for approval" and close the paywall.
2. Listen for updates: `PurchasesDelegate` on iOS, `UpdatedCustomerInfoListener` on Android.
3. Call `getCustomerInfo` when the app comes back to the foreground; a pending purchase can complete while the app is closed.
4. On Android, acknowledge only after the state is `PURCHASED`.

## Example

```swift
// The purchases SDK throws `ErrorCode` values; match the one you handle and let the rest fall through.
func handle(_ error: Error) {
    guard let code = error as? ErrorCode else {
        print("Not a purchases SDK error: \(error)")
        return
    }
    switch code {
    case .paymentPendingError:
        // Not a failure: show a pending message and wait for the customer info update.
        print("Payment pending; do not unlock yet")
    default:
        print("Other purchases error: \(code.description)")
    }
}
```

*Compile-checked: `npm run check:snippets` type-checks this snippet with `swiftc` together with the `ErrorCode.swift` file of the RevenueDot `purchases-ios` fork (checked 2026-10-03).*

## How the RevenueDot SDK reports it

Do not retry the purchase, or the customer starts a second one. Deep dive: [revenuedot.app/errors/payment-pending-error](https://revenuedot.app/errors/payment-pending-error).

## Related

- [What does purchaseCancelledError (code 1) mean in the purchases SDK?](https://revenuedot.app/docs/errors/sdk-purchase-cancelled-error.md)
- [What does productAlreadyPurchasedError (code 6) mean in the purchases SDK?](https://revenuedot.app/docs/errors/sdk-product-already-purchased-error.md)
- [What does Play Billing ITEM_ALREADY_OWNED (7) mean?](https://revenuedot.app/docs/errors/play-billing-item-already-owned.md)
- [What RevenueDot's API errors mean (server codes)](https://revenuedot.app/docs/api/errors.md)

## Source

- [RevenueDot purchases-ios: ErrorCode.swift (the iOS ErrorCode enum)](https://github.com/revenuedot/purchases-ios/blob/revenuedot/main-patches/Sources/Generated/ErrorCode.swift)
- [RevenueDot purchases-android: PurchasesErrorCode.kt (the Android enum)](https://github.com/revenuedot/purchases-android/blob/revenuedot/main-patches/purchases/src/main/kotlin/generated/com/revenuecat/purchases/PurchasesErrorCode.kt)
- [RevenueDot purchases-android: common/errors.kt (backend code mapping)](https://github.com/revenuedot/purchases-android/blob/revenuedot/main-patches/purchases/src/main/kotlin/com/revenuecat/purchases/common/errors.kt)

Checked: 2026-10-03
