---
title: "What does purchaseNotAllowedError (code 3) mean in the purchases SDK?"
description: "purchaseNotAllowedError (code 3) means this device or account may not buy: purchases are restricted, or Google Play billing is unavailable. Retrying does not help."
url: https://revenuedot.app/docs/errors/sdk-purchase-not-allowed-error
---

# What does purchaseNotAllowedError (code 3) mean in the purchases SDK?

The purchases SDK raises purchaseNotAllowedError (code 3) when the device or account is not allowed to make the purchase.

## Quick facts

| | |
|---|---|
| Error | `ErrorCode.purchaseNotAllowedError` (iOS), `PurchasesErrorCode.PurchaseNotAllowedError` (Android), code 3 |
| Where | Purchases SDK (iOS, Android and the hybrid SDKs built on them) |
| What the vendor says | The device or user is not allowed to make the purchase. |

## Cause

- StoreKit 2: `Product.PurchaseError.purchaseNotAllowed`, which Apple documents as the user not being allowed to make purchases. StoreKit 1: `SKError.paymentNotAllowed` and several related codes.
- Android: Play Billing `BILLING_UNAVAILABLE`, `ITEM_NOT_OWNED` and `FEATURE_NOT_SUPPORTED` map here. Google lists an outdated Play Store, an unsupported country and a declined payment method as reasons for `BILLING_UNAVAILABLE`.
- A product change (upgrade or downgrade) requested for a product that is not a subscription.

## Fix

1. Check before you show the paywall: `Purchases.canMakePayments()` on iOS, or the Android equivalent with a callback.
2. Ask the customer to check restrictions: Screen Time or a device management profile on iOS, an up-to-date Play Store, a supported country and a valid payment method on Android.
3. Test on a real store account. Simulators and emulators without one return this error.
4. Do not retry. The block stays until the customer changes a setting.

## 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 .purchaseNotAllowedError:
        // Retrying cannot help: explain the block and show the paywall again on the next launch.
        print("Purchases are not allowed on this device or account")
    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

Deep dive: [revenuedot.app/errors/purchase-not-allowed-error](https://revenuedot.app/errors/purchase-not-allowed-error).

## Related

- [What does Product.PurchaseError.purchaseNotAllowed mean?](https://revenuedot.app/docs/errors/storekit-purchase-error-purchase-not-allowed.md)
- [What does Play Billing BILLING_UNAVAILABLE (3) mean?](https://revenuedot.app/docs/errors/play-billing-billing-unavailable.md)
- [What does Play Billing ITEM_NOT_OWNED (8) mean?](https://revenuedot.app/docs/errors/play-billing-item-not-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-ios: StoreKitError+Extensions.swift](https://github.com/revenuedot/purchases-ios/blob/revenuedot/main-patches/Sources/Error%20Handling/StoreKitError%2BExtensions.swift)
- [RevenueDot purchases-android: google/errors.kt (Play Billing mapping)](https://github.com/revenuedot/purchases-android/blob/revenuedot/main-patches/purchases/src/main/kotlin/com/revenuecat/purchases/google/errors.kt)

Checked: 2026-10-03
