Error Handling
Handling errors in Purchases SDK
This section assumes you've followed our Quickstart section of our Getting Started guide to install and configure our SDK.
Error Handling
If the completion callbacks or listeners on asynchronous methods receive an error argument that is not nil, an error has occurred.
With the exception of NetworkError
, PurchaseCancelledError
or StoreProblemError
, retrying a failed operation with the same arguments won't succeed. For failed purchases, assume the user wasn't charged, unless a StoreProblemError
occurred - in which case the user may or may not have been charged.
iOS Errors
On iOS, when an error has occurred the completion callback will receive a RevenueCat.ErrorCode
object.
When investigating or logging errors, review the errorUserInfo
dictionary, paying attention to the following keys:
rc_code_name
contains a cross-platform error name string that can be used for identifying the error.NSDebugDescriptionErrorKey
contains a description of the error. This description is meant for the developer.
Examples
if let error = error as? RevenueCat.ErrorCode {
print(error.errorCode)
print(error.errorUserInfo)
switch error {
case .purchaseNotAllowedError:
showAlert("Purchases not allowed on this device.")
case .purchaseInvalidError:
showAlert("Purchase invalid, check payment source.")
default: break
}
} else {
// Error is a different type
}
if (error) {
// log error details
NSLog(@"RCError: %@", [error.userInfo objectForKey:RCReadableErrorCodeKey]);
NSLog(@"Message: %@", error.localizedDescription);
NSLog(@"Underlying Error: %@", [error.userInfo objectForKey:NSUnderlyingErrorKey]);
switch ([error code]) {
case RCNetworkError:
showError(@"Network error, check your connection and try again.");
case RCPurchaseNotAllowedError:
showError(@"Purchases not allowed on this device.");
case RCPurchaseInvalidError:
showError(@"Purchase invalid, check payment source.");
default:
break;
}
}
Android Errors
On Android, when an error has occurred, the onError
listener will receive a PurchasesError
object.
When investigating or logging errors, review the properties of PurchasesError
:
code
contains thePurchasesErrorCode
that can be used for identifying the error.message
contains a description of the error. This description is meant for the developer.underlyingErrorMessage
contains a description of the underlying error that caused the error in question, if an underlying error is present.
Examples
with(error) {
// log error details
print("Error: $code")
print("Message: $message")
print("Underlying Error: $underlyingErrorMessage")
when (code) {
PurchasesErrorCode.PurchaseNotAllowedError -> {
showAlert("Purchases not allowed on this device.")
}
PurchasesErrorCode.PurchaseInvalidError -> {
showAlert("Purchase invalid, check payment source.")
}
else -> {}
}
}
Legend
When debugging errors, it's important to consider whether the error was thrown by RevenueCat, Apple, or Google. This can help you pinpoint where to look for a resolution.
Icon | Description |
---|---|
😿 | Error generated from RevenueCat |
🍎 | Error generated from Apple |
🤖 | Error generated from Google |
📦 | Error generated from Amazon |
Error codes common to all methods
😿 INVALID_APP_USER_ID
INVALID_APP_USER_ID
Problem:
Indicates the App User Id is set to an invalid value.
Resolution:
Make sure you're not sending a string over 100 characters or a blocked app user Id.
😿 🍎 🤖 📦 INVALID_CREDENTIALS
INVALID_CREDENTIALS
Problem:
Indicates the application has been configured with an invalid credentials.
Resolution:
If this error occurs before a purchase, ensure you're using the correct API Key from the RevenueCat dashboard.
If this error happens during the purchase flow, make sure your Play Store Credentials and/or App Store Shared Secret and/or Amazon Appstore Credentials are configured correctly in the RevenueCat dashboard.
😿 INVALID_SUBSCRIBER_ATTRIBUTES
INVALID_SUBSCRIBER_ATTRIBUTES
Problem:
Indicates subscriber attributes were unable to be saved.
Resolution:
Make sure that there are no formatting issues when setting subscriber attributes.
😿 NETWORK_ERROR
NETWORK_ERROR
Problem:
Indicates a network error occurred during the operation.
Resolution:
Make sure the device has an internet connection and try again. If you are testing in sandbox, make sure your outgoing connections is turned on. You can find this in XCode under signing & capabilities > App Sandbox > Outgoing connections (Client).
😿 OFFLINE_CONNECTION_ERROR
OFFLINE_CONNECTION_ERROR
Problem:
Indicates the device was offline when attempting a network request.
Resolution:
Make sure the device has an internet connection and try again.
😿 OPERATION_ALREADY_IN_PROGRESS
OPERATION_ALREADY_IN_PROGRESS
Problem:
Indicates an identical operation is already in progress. For example, making two identical purchase attempts at the same time.
Resolution:
Wait for the original operation to complete.
🍎 🤖 📦 STORE_PROBLEM
STORE_PROBLEM
Problem:
This error is forwarded from Apple/Google/Amazon and indicates there was a problem connecting to the App Store, Play Store, or Amazon Appstore.
The problems that will trigger this on iOS:
- Apple server is down (more common in sandbox than production)
- SKErrorUnknown
- SKErrorCloudServiceNetworkConnectionFailed
- SKErrorCloudServiceRevoked
- An SCA purchase flow was initiated.
The problems that will trigger this on Android:
- Google server is down
- Google Play Developer API Quota exceeded
- Invalid Android package name in the RevenueCat dashboard
- Google Billing Client SERVICE_TIMEOUT error
Resolution:
If everything was working while testing, you shouldn't have to do anything to handle this error in production. RevenueCat will automatically retry any purchase failures so no data is lost.
If this occurs while testing in sandbox you can try:
- Repeating the operation later.
- Create a new sandbox user on iOS.
🤷 SIGNATURE_VERIFICATION_FAILED
SIGNATURE_VERIFICATION_FAILED
Problem:
Indicates that the SDK detected a request was tampered.
Resolution:
- Ensure that a proxy is not modifying responses from our API.
- See the docs for more information.
😿 UNEXPECTED_BACKEND_RESPONSE_ERROR
UNEXPECTED_BACKEND_RESPONSE_ERROR
Problem:
Indicates the SDK received an unexpected response from the server.
iOS sub error codes:
loginResponseDecoding
: Unable to decode response returned from login.postOfferIdBadResponse
: Unable to decode response returned from posting offer for signing.postOfferIdMissingOffersInResponse
: Missing offers from response returned from posting offer for signing.postOfferIdSignature
: Signature error encountered in response returned from posting offer for signing.getOfferUnexpectedResponse
: Unknown error encountered while getting offerings.customerInfoNil
: Unable to instantiate a CustomerInfoResponse, CustomerInfo in response was nil.customerInfoResponseParsing
: Unable to instantiate a CustomerInfoResponse due to malformed json.
Resolution:
Report the error with the full error object.
😿 UNKNOWN_BACKEND_ERROR
UNKNOWN_BACKEND_ERROR
Problem:
Indicates there was an unknown server error.
Resolution:
Report the error with the full error object.
🤷 UNKNOWN
UNKNOWN
Problem:
Indicates an unknown error occurred. Possible causes:
- The subscriber has reached the maximum number of Apple receipts allowed. This can be an indication of an implementation error regarding identifying users. Take a look at our best practices for identifying users for common implementation mistakes.
Resolution:
Help us fix it.
Purchasing Errors
😿 RECEIPT_ALREADY_IN_USE
RECEIPT_ALREADY_IN_USE
Problem:
Indicates there is an identical receipt already in use by another subscriber.
Resolution:
The user will either need to log in as the App User Id that already owns the receipt or restore purchases to re-sync the receipt with their current account. We recommend checking out the 'Transfer purchases' restore behavior.
🍎 🤖 📦 INVALID_RECEIPT
INVALID_RECEIPT
Problem:
Indicates the receipt is malformed or invalid.
Resolution:
This error indicates an error with configuration and usually occurs in the sandbox environment.
If testing with StoreKit Configuration Files:
- Follow StoreKit test guide
- Re-upload the StoreKit certificate after making any changes to products or code-signing
- All products in StoreKit file are listed in the RevenueCat dashboard
Some other places to check:
- Bundle ID and shared secret are set correctly for your app
🍎 INVALID_APPLE_SUBSCRIPTION_KEY
INVALID_APPLE_SUBSCRIPTION_KEY
Problem:
Indicates that the Apple Subscription Key is invalid or not present.
Resolution:
In order to provide Subscription Offers you must first generate a subscription key.
🍎 MISSING_RECEIPT_FILE
MISSING_RECEIPT_FILE
Problem:
Indicates there is no receipt file available on the device. This is more common in sandbox testing.
Resolution:
Make sure you're signed into the device with a valid Apple account. In Sandbox, you may have to make a purchase to generate a receipt before attempting the operation. This error can occur fairly often in the sandbox environment. In sandbox a receipt is generated when a user makes a purchase and is saved against the sandbox account. While in production a receipt is generated when a user downloads the app and is saved against the Apple account.
🍎 INELIGIBLE_ERROR
INELIGIBLE_ERROR
Problem:
Indicates that the user is ineligible for the specific Subscription Offer.
Some possible causes:
- User has already used this Offer
- Offer not available in specific region
- User has no current or previous subscription
Resolution:
If a user is not eligible for a Subscription Offer, be sure to update your UI to reflect normal pricing or terms. .paymentDiscount(...)
is the best way to check for Subscription Offer eligibility. If you are testing in sandbox and already tested a purchase with that offer, you may want to create a new sandbox user to try again.
🍎 🤖 INSUFFICIENT_PERMISSIONS_ERROR
INSUFFICIENT_PERMISSIONS_ERROR
Problem:
Indicates the device does not have sufficient permissions to make in-app purchases.
Resolution:
Make sure you're signed into a physical device with a valid Apple or Google account that has permissions to make purchases.
🍎 🤖 PAYMENT_PENDING_ERROR
PAYMENT_PENDING_ERROR
Problem:
Additional action is required by the user before granting entitlement. For example, a user might choose to purchase your in-app product at a physical store using cash, or a parental control on a child's device may require approval before purchasing.
Resolution:
Confirm to the user that they've started the pending purchase, and to complete it, they should follow instructions that are given to them from Apple or Google.
🍎 PRODUCT_ALREADY_PURCHASED
PRODUCT_ALREADY_PURCHASED
🤖 ITEM_ALREADY_OWNED
ITEM_ALREADY_OWNED
Problem:
Indicates that the product is already active for the user.
Resolution:
If testing in sandbox:
- Subscription IAP: Wait for the subscription to automatically cancel and try again.
- Non-subscription IAP: Create a new sandbox user.
If this occurs in production, make sure the user restores purchases to re-sync any transactions with their current App User Id.
🍎 PRODUCT_NOT_AVAILABLE_FOR_PURCHASE
PRODUCT_NOT_AVAILABLE_FOR_PURCHASE
🤖 ITEM_UNAVAILABLE
ITEM_UNAVAILABLE
Problem:
Indicates the product is not available for purchase by the device or user.
Resolution:
Ensure you're attempting to purchase a product that's available for the device / user.
🍎 🤖 PURCHASE_CANCELLED
PURCHASE_CANCELLED
Problem:
Indicates the user cancelled their purchase and was not charged.
On iOS, this can also mean the Apple account already owns the product. The user can restore purchases to re-sync any transactions with their current App User Id.
Resolution:
No action required. The user decided not to proceed with their in-app purchase.
🍎 📦 PURCHASE_INVALID
PURCHASE_INVALID
🤖 DEVELOPER_ERROR
DEVELOPER_ERROR
Problem:
Indicates one of the provided arguments for the purchase was invalid, including the payment method.
The problems that will trigger this on Android:
- Google Billing Client DEVELOPER_ERROR
The problems that will trigger this on iOS:
Resolution:
Ensure the device payment method is valid and all arguments passed in are correct.
🍎 🤖 PURCHASE_NOT_ALLOWED
PURCHASE_NOT_ALLOWED
Problem:
Indicates the device or user is not allowed to make the purchase.
The problems that will trigger this on Android:
- Google Billing Client FEATURE_NOT_SUPPORTED
The problems that will trigger this on iOS:
- SKErrorPrivacyAcknowledgementRequired
- SKErrorPaymentNotAllowed
- SKErrorCloudServicePermissionDenied
- SKErrorOverlayInvalidConfiguration
- SKErrorUnsupportedPlatform
- SKErrorIneligibleForOffer
- SKErrorClientInvalid
Resolution:
Make sure the device and user are allowed to make in-app purchases. Try the following troubleshooting steps:
- Make sure your device/emulator is completely updated.
- Try running on device. Sometimes the emulator glitches out and it must be restarted. Overall, testing on device is more reliable.
- Restart your device/emulator.
- Make sure you're logged in with a Google account.
- If you're running on an emulator, make sure it has Google Play installed.
Restoring Errors
🍎 🤖 INVALID_RECEIPT
INVALID_RECEIPT
Problem:
Indicates the receipt is malformed or invalid.
Resolution:
Receipt validation failed, no action required.
🍎 MISSING_RECEIPT_FILE
MISSING_RECEIPT_FILE
Problem:
Indicates there is no receipt file available on the device. This is more common in sandbox testing.
Resolution:
Make sure you're signed into the device with a valid Apple account. For Sandbox testing, you may have to make a purchase to generate a receipt before attempting the operation. In Sandbox a receipt is generated when a user makes a purchase and is saved against the sandbox account. While in production a receipt is generated when a user downloads the app and is saved against the Apple account.
📦 ERROR_FINDING_RECEIPT_SKU
ERROR_FINDING_RECEIPT_SKU
Problem:
Indicates there is no SKU available from the token.
📦 ERROR_FETCHING_RECEIPTS
ERROR_FETCHING_RECEIPTS
Problem:
Indicates there was an error fetching receipts.
📦 ERROR_FETCHING_RECEIPT_INFO
ERROR_FETCHING_RECEIPT_INFO
Problem:
Indicates there was an error fetching information about the receipt.
📦 ERROR_OBSERVER_MODE_NOT_SUPPORTED
ERROR_OBSERVER_MODE_NOT_SUPPORTED
Problem:
Observer Mode is not currently supported for Amazon.
Resolution:
Disable Observer Mode.
Next Steps
- You're set up to handle errors, time to start making purchases in sandbox
Updated 7 days ago