This is the final article in our series on implementing in-app purchases for iOS. Follow the links below to catch up on the previous ones:
- iOS in-app purchases, part 1: App Store Connect and project configuration
- iOS in-app purchases, part 2: purchase initialization and processing
- iOS in-app purchases, part 3: testing purchases in Xcode
- iOS in-app purchases, part 4: server-side receipt validation
- iOS in-app purchases: the list of SKError codes and how to handle them
In this post, I will address the various kinds of SKErrors you might encounter: what problems they reveal and what to do about them. For each error, we will work out three aspects: why it occurs, how to handle them, and what message to display in the error notification.
SKError.Code.unknown
Integer error code: 0
What it means: An error occurred for an unknown reason.
How to fix it: No action is needed from the developer’s side. This error is also possible on iOS 14 or later when using the simulator. In that case, use StoreKit local testing or a real device for testing in-app purchases. You could also try a simulator running iOS 13.

SKError.Code.clientInvalid
Integer error code: 1
What it means: The user cannot make a purchase. For example, a child tries to buy something with parental controls enabled.
How to fix it: No action is needed from the developer’s side.

SKError.Code.paymentCancelled
Integer error code: 2
What it means: The user got to the payment screen, but changed their mind about making a purchase and clicked “cancel”.
How to fix it: From a technical point of view, no error occurred and nothing needs to be done. From a marketing point of view, you could try additional techniques to convince the user to purchase. For example, you could offer them a discount.
What message to display: You have two options here. The easiest one is to not show anything. However, you can also try winning a user back with a message like this: “You have canceled your purchase. Are you interested in trying a subscription at a discounted price?”
SKError.Code.paymentInvalid
Integer error code: 3
What it means: For some reason, the payment failed: the card was expired or there were not enough funds for this purchase.
How to fix it: No action is needed from the developer’s side.


SKError.Code.paymentNotAllowed
Integer error code: 4
What it means: The device is not allowed to authorize payments. This could be due to parental controls restricting purchases, the device is limited due to an active enterprise or corporate policy, or it’s simply a device or user that isn’t authorized to make purchases.
How to fix it: No action is needed from the developer’s side.

SKError.Code.storeProductNotAvailable
Integer error code: 5
What it means: The user is trying to buy a product that is not available for the region in which this store is used.
How to fix it: The developer needs to check products for their availability in the user’s store and region. For this, you can use Storefront.

SKError.Code.cloudServicePermissionDenied
Integer error code: 6
What it means: The user has not allowed access to Cloud service information. This error message is not commonly encountered by users or developers. It is usually related to attempting to access a cloud service like Apple Music, but the user has denied app access to their Apple Music in settings.
How to fix it: No action is needed from the developer’s side.

SKError.Code.cloudServiceNetworkConnectionFailed
Integer error code: 7
What it means: The device was not connected to the Internet when making a purchase.
How to fix it: No action is needed from the developer’s side.

SKError.Code.cloudServiceRevoked
Integer error code: 8
What it means: This device doesn’t have access to the StoreKit payment service. Commonly, this error occurs in Sandbox.
How to fix it: Create a new Sandbox user or just try repeating the operation.

SKError.Code.privacyAcknowledgementRequired
Integer error code: 9
What it means: The user has not yet acknowledged Apple’s privacy policy for Apple Music.
How to fix it: No action is needed from the developer’s side.

SKError.Code.unauthorizedRequestData
Integer error code: 10
What it means: Your app ID doesn’t contain the required entitlement for using StoreKit.
How to fix it: You need to finish the setup process of in-app purchases for your app.

SKError.Code.invalidOfferIdentifier
Integer error code: 11
What it means: The user is trying to buy a product with an invalid offer identifier attached.
How to fix it: The offer identifier has either not been set up in App Store Connect, or it has been revoked. Either way, you’ll want to change this product offering in your app to use a valid offer identifier.

SKError.Code.invalidSignature
Integer error code: 12
What it means: The signature for the promotional offer for the StoreKit request was generated incorrectly.
How to fix it: Check how the signature is generated and fix the errors. If you use Adapty, download the Subscription Key.

SKError.Code.missingOfferParams
Integer error code: 13
What it means: Parameters of the promotional offer are missing.
How to fix it: Make sure that all parameters of SKPaymentDiscount
are present.

SKError.Code.invalidOfferPrice
Integer error code: 14
What it means: The user is trying to buy a product with an invalid price. This can happen if the base price is changed such that it is now lower than the discounted price.
How to fix it: Set the updated price for this offer in the App Store.

SKError.Code.overlayCancelled
Integer error code: 15
What it means: The user has cancelled a purchase or other transaction within the in-app purchase overlay. When a user attempts to make an in-app purchase, the StoreKit framework presents an overlay that allows the user to complete the transaction. If the user cancels the purchase at any point during this process, the framework returns this error code.
How to fix it: You can handle this error code by dismissing the in-app purchase overlay and notifying the user that the transaction has been cancelled. You should also ensure that any data related to the cancelled transaction is properly handled and cleaned up in your app.

SKError.Code.overlayInvalidConfiguration
Integer error code: 16
What it means: There is a problem with the configuration of the in-app purchase overlay. This error can occur if there is missing or incorrect information in the configuration of your in-app purchases, such as missing product identifiers or incorrect payment configuration settings.
How to fix it: Check the configuration of your in-app purchases and ensure that all required fields are properly configured. This may involve checking your product identifiers, verifying your payment configuration settings, and ensuring that your app is properly configured to handle in-app purchases.

SKError.Code.overlayTimeout
Integer error code: 17
What it means: The in-app purchase overlay has timed out while waiting for a response from the user or the App Store.
How to fix it: Ensure that your app is properly configured to handle in-app purchases and that your code is properly handling the purchase flow. You may also want to consider optimizing the performance of your app to reduce the likelihood of timeouts or delays during in-app purchases.

SKError.Code.ineligibleForOffer
Integer error code: 18
What it means: The user is not eligible for a particular offer or promotion associated with an in-app purchase. This error can occur if the user does not meet the eligibility requirements for the offer, such as geographic location, age, or other criteria set by the app developer or the App Store.
How to fix it: Review the eligibility criteria for the offer and ensure that they are properly documented and communicated to users. You may also want to consider providing alternative offers or promotions for users who are not eligible for the original offer.

SKError.Code.unsupportedPlatform
Integer error code: 19
What it means: The app is running on an unsupported platform or device. This error can occur if the app is attempting to make an in-app purchase on a device or platform that is not supported by the StoreKit framework or the App Store. For example, some in-app purchases may be restricted to certain iOS versions or devices, and attempting to make a purchase on an unsupported platform could result in such an error.
How to fix it: Review the requirements and limitations of your in-app purchases and ensure that they are compatible with the platforms and devices that your app supports.

SKError.Code.overlayPresentedInBackgroundScene
Integer error code: 20
What it means: The in-app purchase overlay was presented in a background scene instead of the active scene.
How to fix it: Ensure that your app is properly managing its scenes and that the in-app purchase overlay is presented in the active scene. You may also want to consider optimizing the performance of your app to reduce the likelihood of background scenes becoming active during the in-app purchase process.

Conclusion
Correct error handling improves the user experience and can return at least some of those users who could not pay for the subscription immediately for some reason. These are the most common mistakes when implementing purchases in an iOS app:
- SKError.Code.unknown, an unknown error;
- SKError.Code.paymentCancelled, when the user cancels the purchase;
- SKError.Code.paymentInvalid, when the payment can’t be processed.
Actually, error handling and purchase implementation are cumbersome processes. So I would recommend trying Adapty for iOS, which makes implementing in-app purchases easier and provides other benefits, such as subscription analytics, cohort analysis, A/B tests for paywalls, and server-side receipt validation.