SDK error · code 4

purchaseInvalidError (error code 4): Purchase invalid

What it means

purchaseInvalidError (code 4) means the store or the SDK refused the purchase request because a parameter was wrong: an invalid payment, a quantity outside 1 to 10, an unsupported product, or a Google Play DEVELOPER_ERROR. It points to a setup bug, not a temporary fault. Fix the product or the call, and do not grant access.

Code

4

iOS (Swift)

ErrorCode.purchaseInvalidError

Android (Kotlin)

PurchasesErrorCode.PurchaseInvalidError

Causes

Why the SDK returns purchaseInvalidError

  • StoreKit 1: SKError.paymentInvalid (a payment parameter the App Store did not recognize) and unauthorizedRequestData (a property used without the required entitlement).
  • StoreKit 2: StoreKitError.unsupported, which Apple documents as an operation that does not support the product.
  • The SDK rejects a purchase quantity below 1 or above 10 before it reaches the store (PurchaseParams.swift).
  • Android: Play Billing DEVELOPER_ERROR, which Google describes as improper API usage such as incorrect parameters (Google docs). Add-on products on a store other than Google Play also raise it.
  • The backend answered 7105, 7106, or on iOS 7870, 8139 or 8140. On Android the web redemption codes 7849 and 7853 land here too.
Backend codeMeaning
7105Invalid payment mode, or the intro price was not provided.
7106The product ID for a Google receipt was not provided.
7870Unknown virtual currency code (iOS mapping).
8139Duplicate virtual currency transaction (iOS mapping).
8140Invalid idempotency key (iOS mapping).
7849Invalid web redemption token. The Android SDK maps it to purchaseInvalidError; iOS maps it to invalidWebPurchaseToken.
7853Expired web redemption token. The Android SDK maps it to purchaseInvalidError; iOS maps it to expiredWebPurchaseToken.

Fix

How to fix purchaseInvalidError

  1. 01

    Read the message

    The message and the underlying error name the bad parameter. On Android, Google's debug message for DEVELOPER_ERROR is in underlyingErrorMessage.

  2. 02

    Check the quantity and product type

    Pass a quantity from 1 to 10 only on products that allow it, and use the right product type (subscription or in-app product) for the call.

  3. 03

    Check the product setup in the store

    Compare the product ID, type and status in App Store Connect or Play Console with what the offering sends. A product that is not ready can fail here.

  4. 04

    Update the SDK and test again

    A StoreKit option that is new to the OS may need a newer SDK. Update and retry on a real account.

In your app

How to handle it in code

  • Do not retry the same call. A bad parameter fails the same way every time.
  • Show a generic "purchase could not be started" message to the customer and send the details to your own logging.
  • Do not grant access.
Match the errorSwift · Kotlin
// Swift
do {
  let result = try await Purchases.shared.purchase(package: package)
} catch let error as ErrorCode where error == .purchaseInvalidError {
  // handle purchase invalid
}

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

On RevenueDot: RevenueDot does not answer 7105 or 7106. A Google one-time purchase posted without product_ids gets code 7103, which the SDK reports as invalidReceiptError. RevenueDot does answer 7849 and 7853 for web redemption links, and on Android those arrive as this error.

FAQ

purchaseInvalidError: questions people ask

What causes purchaseInvalidError in RevenueCat?

A bad parameter in the purchase request: Apple's paymentInvalid, a quantity outside 1 to 10, an unsupported product, or Google Play's DEVELOPER_ERROR. It is a setup bug, so retrying does not help.

What is DEVELOPER_ERROR in Google Play Billing?

Google's code for improper API usage, such as incorrect parameters (Google docs). RevenueCat reports it as purchaseInvalidError.

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

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

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