Code
4
SDK error · code 4
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.purchase
Android (Kotlin)
PurchasesErrorCode.Purchase
Causes
SKError.paymentInvalid (a payment parameter the App Store did not recognize) and unauthorizedRequestData (a property used without the required entitlement).StoreKitError.unsupported, which Apple documents as an operation that does not support the product.quantity below 1 or above 10 before it reaches the store (PurchaseParams.swift).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.| Backend code | Meaning |
|---|---|
| 7105 | Invalid payment mode, or the intro price was not provided. |
| 7106 | The product ID for a Google receipt was not provided. |
| 7870 | Unknown virtual currency code (iOS mapping). |
| 8139 | Duplicate virtual currency transaction (iOS mapping). |
| 8140 | Invalid idempotency key (iOS mapping). |
| 7849 | Invalid web redemption token. The Android SDK maps it to purchaseInvalidError; iOS maps it to invalidWebPurchaseToken. |
| 7853 | Expired web redemption token. The Android SDK maps it to purchaseInvalidError; iOS maps it to expiredWebPurchaseToken. |
Fix
The message and the underlying error name the bad parameter. On Android, Google's debug message for DEVELOPER_ERROR is in underlyingErrorMessage.
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.
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.
A StoreKit option that is new to the OS may need a newer SDK. Update and retry on a real account.
In your app
// 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
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.
Google's code for improper API usage, such as incorrect parameters (Google docs). RevenueCat reports it as purchaseInvalidError.
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
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