What does Product.PurchaseError.invalidOfferPrice mean?
Product.PurchaseError.invalidOfferPrice means the App Store judged the price of the offer you tried to apply to be invalid.
Quick facts#
| Error | Product.PurchaseError.invalidOfferPrice |
| 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 price of the offer isn't valid. |
Cause#
- Apple's case page gives only that one line and lists no causes, so the exact trigger is not documented.
- Apple says promotional offers, with their price, are set up in App Store Connect before the app can use them (promotionalOffer option). The offer the app applies must be one that still exists there for that product.
- It is a sibling of
invalidOfferIdentifierandinvalidOfferSignature: the offer is rejected because of its data, not because the person cancelled or the network failed.
Fix#
- Read the offer from
product.subscription?.promotionalOffersafter a freshProduct.products(for:)call, and show itsdisplayPrice, so the price in your UI is the one the App Store holds. - Open the offer in App Store Connect and check that it is active for the product and for the storefront the person uses.
- Do not reuse a signed offer after a failed attempt. Ask your server for a new signature before you try again.
- Test the same offer in the sandbox. If it fails there too, the offer configuration is the problem, not the device.
Example#
Swift
import StoreKit
// Show the price the App Store holds for the offer, and react to the rejection by reloading the product.
func offerPrice(of product: Product, offerID: String) -> String? {
product.subscription?.promotionalOffers.first { $0.id == offerID }?.displayPrice
}
func buy(_ product: Product, options: Set<Product.PurchaseOption>) async {
do {
_ = try await product.purchase(options: options)
} catch Product.PurchaseError.invalidOfferPrice {
print("The App Store says the offer price is not valid; reload the product and its offers")
} 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.invalidOfferPrice to ErrorCode.invalidPromotionalOfferError (code 34), together with invalidOfferIdentifier, invalidOfferSignature and missingOfferParameters.
Related#
- What does Product.PurchaseError.invalidOfferSignature mean?
- What does Product.PurchaseError.invalidOfferIdentifier mean?
- What does Product.PurchaseError.ineligibleForOffer mean?
Source#
- Apple: Product.PurchaseError.invalidOfferPrice
- Apple: promotionalOffer purchase option
- RevenueDot purchases-ios: StoreKitError+Extensions.swift (how the SDK maps StoreKit 2 errors)
Checked: 2026-10-03