What does Product.PurchaseError.productUnavailable mean?
Product.PurchaseError.productUnavailable means the App Store reports that this product is not available to buy.
Quick facts#
| Error | Product.PurchaseError.productUnavailable |
| Where | StoreKit 2, Swift (Product.purchase(options:)) |
| 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 product is not available. |
Cause#
- The App Store has the product but will not sell it to this customer right now. Apple's page for the case gives no further reason.
- Apple notes that if an identifier is invalid or the App Store cannot find it,
Product.products(for:)leaves it out of the result instead of throwing (products(for:)). A product you hold but cannot buy is a different state from one that never loaded. - Products are sold per region, and Apple tells developers to keep their own list of identifiers and the storefronts where they are available (Storefront).
Fix#
- Check the product in App Store Connect: it must exist, have complete metadata and be available in the customer's region.
- Compare the identifier in your code character by character with the one in App Store Connect.
- Reload products and compare the IDs you asked for with the IDs that came back, to see which one is missing.
- Hide or disable the buy button for the product until it loads, and do not retry the same call in a loop.
Example#
Swift
import StoreKit
// Compare what you asked for with what came back, so a missing product is a log line instead of a silent dead button.
func buy(id: String) async {
do {
guard let product = try await Product.products(for: [id]).first else {
print("The App Store returned no product for \(id); check the identifier and availability")
return
}
_ = try await product.purchase()
} catch Product.PurchaseError.productUnavailable {
print("\(id) exists but cannot be bought right now")
} 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 Product.PurchaseError.productUnavailable to ErrorCode.productNotAvailableForPurchaseError (code 5). In RevenueDot, make sure the product's store identifier equals the App Store identifier. See what productNotAvailableForPurchaseError means.
Related#
- What does productNotAvailableForPurchaseError (code 5) mean in the purchases SDK?
- What does StoreKitError.notAvailableInStorefront mean?
- What does Play Billing ITEM_UNAVAILABLE (4) mean?
Source#
- Apple: Product.products(for:)
- Apple: Product.PurchaseError.productUnavailable
- Apple: Product.PurchaseError
- RevenueDot purchases-ios: StoreKitError+Extensions.swift (how the SDK maps StoreKit 2 errors)
Checked: 2026-10-03