What does StoreKitError.userCancelled mean?

StoreKitError.userCancelled means the person cancelled, so nothing was bought and nothing is broken.

Quick facts#

Error StoreKitError.userCancelled
Where StoreKit 2, Swift (StoreKitError)
Available since iOS 15.0, iPadOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, visionOS 1.0
What the vendor says The user canceled.

Cause#

  • The person dismissed a StoreKit flow, such as the purchase confirmation sheet, before finishing it.
  • A purchase made with Product.purchase() reports a cancel as the result Product.PurchaseResult.userCancelled, which Apple documents as the user cancelling the purchase. The error case is the same outcome in error form, so handle both the same way.
  • Apple documents no other cause. A cancel is the person's choice, not an App Store failure.

Fix#

  1. Do not show an error. A cancel is a normal step in a purchase funnel.
  2. Leave the paywall open with its products loaded, so the person can choose again.
  3. Count cancels apart from failures in your analytics, so real errors stay visible.
  4. Do not unlock anything and do not retry for the person.

Example#

Swift
import StoreKit

// Treat a cancel as an outcome, not an error: no alert, no retry, no unlock.
func buy(_ product: Product) async {
    do {
        switch try await product.purchase() {
        case .userCancelled:
            print("Cancelled by the person; leave the paywall as it is")
        case .pending:
            print("Waiting for approval; do not unlock yet")
        case .success(let verification):
            print("Bought: \(verification)")
        @unknown default:
            break
        }
    } catch StoreKitError.userCancelled {
        // The error form of the same outcome.
        print("Cancelled by the person; leave the paywall as it is")
    } catch {
        print("Purchase failed: \(error)")
    }
}

Compile-checked: npm run check:snippets type-checks this snippet with swiftc against the Apple SDK (macOS target, checked 2026-10-03).

How the RevenueDot SDK reports it#

The RevenueDot purchases-ios fork maps StoreKitError.userCancelled to ErrorCode.purchaseCancelledError (code 1) and sets userCancelled on the purchase result. RevenueDot's server never sees a cancelled purchase, because the SDK stops before it posts a receipt. See what purchaseCancelledError means.

Source#

Checked: 2026-10-03

Edit this page on GitHub ↗ View as Markdown Last updated