What’s new in Apphud: Free Trials Performance Report, Paddle Integration, SDK Updates, and moreLet’s see
Apphud
Why Apphud?PricingContact
Ren
Ren
April 27, 2023
4 min read

SKError: Subscription Purchase Errors explained simply

When developing an iOS app that includes In-App Purchases, it's important to be familiar with the various error codes that can be returned by the StoreKit framework.

SKError: Subscription Purchase Errors explained simply

These error codes, known as SKError codes, provide information on why a specific In-App Purchase payment request failed. In this article, we'll take a look at each of the SKError codes and provide guidance on how to handle them.

Error codes explanation

  • SKErrorUnknown.
    This error code indicates that an unknown error has occurred. This is the most common error code after SKErrorPaymentCancelled. We will explain how to handle this unknown error code below in this article.
  • SKErrorClientInvalid.
    This error code indicates that the user is not authorized to make the purchase. This can occur if the user has not set up a payment method or if their payment method has expired. To handle this error, prompt the user to update their payment information.
  • SKErrorPaymentCancelled.
    This error code indicates that the user has canceled the purchase manually. To handle this error, you can dismiss the purchase screen and return the user to the previous screen. You should not provide any message to the user in this case.
  • SKErrorPaymentInvalid.
    This error code indicates that the purchase was not completed because the payment was invalid. This can occur if the user's credit card was declined or if there were insufficient funds. To handle this error, prompt the user to update their payment information.
  • SKErrorPaymentNotAllowed.
    This error code indicates that the user is not authorized to make the purchase. This can occur if the user has restricted in-app purchases or if the developer has not set up their app for in-app purchases correctly. To handle this error, prompt the user to update their settings or contact the developer for assistance.
  • SKErrorStoreProductNotAvailable.
    This error code indicates that the requested product is not available in the App Store. This can occur if the product has been removed or if it is not yet available in the user's country. To handle this error, inform the user that the product is not available and suggest an alternative.
  • SKErrorCloudServicePermissionDenied.
    This error code indicates that the user has not been granted permission to access their iCloud account. This can occur if the user has restricted access to their iCloud account. To handle this error, prompt the user to update their settings or contact the developer for assistance.
  • SKErrorCloudServiceNetworkConnectionFailed.
    This error code indicates that a network connection error has occurred while attempting to access the user's iCloud account. To handle this error, inform the user that a network error has occurred and advise them to try again later.
  • SKErrorCloudServiceRevoked.
    This error code indicates that the user's iCloud account has been revoked. This can occur if the user has deleted their account or if their account has been suspended. To handle this error, prompt the user to update their settings or contact the developer for assistance.
  • SKErrorPrivacyAcknowledgementRequired.
    This error code indicates that the user must acknowledge the app's privacy policy before making a purchase. To handle this error, prompt the user to review and accept the app's privacy policy.

More about SKErrorUnknown (SKErrorDomain Code 0)

In the context of the StoreKit framework, NSUnderlyingError is an error object that can be returned as part of a SKError object. When an in-app purchase request fails, especially with the code SKErrorUnknown, the SKError object may include an NSUnderlyingError object that provides additional details about the cause of the error.

"error": {
    "code": "E_UNKNOWN",
    "message": "An unknown error occurred",
    "domain": "SKErrorDomain",
    "userInfo": {
      "NSUnderlyingError": {
        "code": "504",
        "message": "underlying error",
        "domain": "ASDErrorDomain",
        "userInfo": {
          "NSUnderlyingError": {
            "code": "305",
            "message": "underlying error",
            "domain": "AMSErrorDomain",
            "userInfo": {
							...
              "NSLocalizedDescription": "Server Error",
              "NSLocalizedFailureReason": "Verification Required",
            }
						...

In the code example above, you can find the localized failure reason: 'Verification Required', which is actually the real reason for the payment failure. The user has probably been prompted to verify their payment method by the system.

Note that this particular example has two levels of underlying errors: one with code 504 and another with code 305. You should always search deeply to find the last underlying error and get its failure reason.

To access the underlying error object in this scenario, you would first check the code property of the SKError object to determine that it is a SKErrorUnknown. You could then call the userInfo method on the SKError object to retrieve any additional information, including the NSUnderlyingError object. 

This is a basic example of how to get the localized failure reason of the SKError code for iOS in-app purchases:

extension NSError {
    var underlyingErrorDescription: String? {
        
        if let error = userInfo["NSUnderlyingError"] as? NSError {
            if let innerError = error.userInfo["NSUnderlyingError"] as? NSError {
                return innerError.localizedFailureReason
            }
            return error.localizedFailureReason
        }
        
        return nil
    }
}

Handling NSUnderlyingError objects in the context of StoreKit can be important for diagnosing and resolving issues related to in-app purchases. By accessing the underlying error object, you can gain more insight into the root cause of the error and provide more helpful guidance on how to resolve the issue.


Conclusion

In conclusion, being familiar with the SKError codes is an essential part of developing an iOS app that includes in-app purchases. By understanding each error code and how to handle it, you can provide a better user experience and ensure that your app is successful.

The Apphud SDK automatically handles necessary error codes. With Apphud, you won't miss any successful purchases, even if the purchase has been completed outside the app after the payment verification has been updated. Sign up for Apphud today and let us provide you with subscription infrastructure. 

Ren
Ren
Co-founder at Apphud
Ex iOS app and game developer. 11 years in the industry since iOS 3. More than 50 apps are in the background with 4 exits. Entrepreneur and traveler.