SDK error · code 3

purchaseNotAllowedError (error code 3): Purchase not allowed

What it means

purchaseNotAllowedError (code 3) means the device or account is not allowed to buy: purchases are restricted on the device, Google Play billing is unavailable, or the app is not allowed to use billing. Retrying will not help until the customer changes a device or account setting. Check Purchases.canMakePayments() first, explain the block, and do not grant access.

Code

3

iOS (Swift)

ErrorCode.purchaseNotAllowedError

Android (Kotlin)

PurchasesErrorCode.PurchaseNotAllowedError

Causes

Why the SDK returns purchaseNotAllowedError

  • StoreKit 1: SKError.paymentNotAllowed (the user is not allowed to authorize payments), clientInvalid, cloudServicePermissionDenied, privacyAcknowledgementRequired, overlayInvalidConfiguration and unsupportedPlatform (source).
  • StoreKit 2: Product.PurchaseError.purchaseNotAllowed, which Apple documents as the user not being allowed to make purchases.
  • Android: Play Billing BILLING_UNAVAILABLE, ITEM_NOT_OWNED and FEATURE_NOT_SUPPORTED. Google lists an outdated Play Store, an unsupported country and a declined payment method as reasons for BILLING_UNAVAILABLE (Google docs).
  • Android: a product change (upgrade or downgrade) was requested for a product that is not a subscription.
  • Android Test Store: looking up an earlier purchase for a product change always fails with "No active purchase found for product".

Fix

How to fix purchaseNotAllowedError

  1. 01

    Check before you show the paywall

    Call Purchases.canMakePayments() on iOS, or Purchases.canMakePayments(context, callback = ...) on Android, which answers through a callback. If it says no, show a message instead of the purchase button.

  2. 02

    Ask the customer to check restrictions

    On iOS, parental controls or Screen Time can block in-app purchases. On Android, the Play Store must be up to date, the country must support billing, and a valid payment method must be on file.

  3. 03

    Test on a real account

    Simulators and emulators without a store account return this error. Sign in to a sandbox Apple account or a Play license tester account. See test purchases without real money.

  4. 04

    Fix the product change

    On Android, only subscriptions can be replaced. Pass a subscription product and check the replacement mode.

In your app

How to handle it in code

  • Do not retry. The block stays until the customer changes a setting.
  • Tell the customer why: "Purchases are turned off on this device" or "Google Play billing is not available". Link to the device setting if you can.
  • Do not grant access, and do not hide the paywall for good. Show it again on the next launch, because the setting may change.
Match the errorSwift · Kotlin
// Swift
do {
  let result = try await Purchases.shared.purchase(package: package)
} catch let error as ErrorCode where error == .purchaseNotAllowedError {
  // handle purchase not allowed
}

// Kotlin
if (error.code == PurchasesErrorCode.PurchaseNotAllowedError) { /* ... */ }

FAQ

purchaseNotAllowedError: questions people ask

Why does purchaseNotAllowedError appear on a real device?

Usually the device has in-app purchases restricted by parental controls or Screen Time (iOS), or Google Play billing is unavailable because of an old Play Store, an unsupported country or a declined payment method (Android).

What is BILLING_UNAVAILABLE in Google Play Billing?

A user billing error: an outdated Play Store, an unsupported country or a declined payment method, among others. Google says to retry manually after the customer fixes it (Google docs). RevenueCat reports it as purchaseNotAllowedError.

How do I check for purchaseNotAllowedError in React Native and Flutter?

In React Native, compare error.code with PURCHASES_ERROR_CODE.PURCHASE_NOT_ALLOWED_ERROR. In Flutter, convert the PlatformException with PurchasesErrorHelper.getErrorCode(e) and compare the result with PurchasesErrorCode.purchaseNotAllowedError.

Get started

Keep the RevenueCat SDK. Change the backend.

RevenueDot answers the same SDK calls with the same error codes. Start free on RevenueDot Cloud, free up to $10,000 a month in tracked revenue.

Already have an account? Sign in · Prefer your own servers? Self-host free