What does Product.PurchaseError.missingOfferParameters mean?
Product.PurchaseError.missingOfferParameters means the purchase named an offer but did not carry all the parameters the App Store needs to apply it.
Quick facts#
| Error | Product.PurchaseError.missingOfferParameters |
| 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 offer parameters are missing. |
Cause#
- Apple's case page gives only that one line. It lists no causes.
- A promotional offer needs several values: the offer ID, and either the key ID, nonce, signature and timestamp from your server, or a compact JWS signed on your server. The
promotionalOffer(offerID:keyID:nonce:signature:timestamp:)option takes the first group. - From iOS 26 the signature-and-nonce option is deprecated in the StoreKit interface in favor of
promotionalOffer(_:compactJWS:), so apps that mix the two styles can leave a part out.
Fix#
- Build the offer option from one server response that contains every value, and pass nothing partial.
- Move to the JWS option (
promotionalOffer(_:compactJWS:)) when your minimum iOS version allows it. It carries the signed offer as one string. - Check that your server returns the key ID, the nonce, the timestamp and the signature, and that the app does not drop one while decoding.
- Request a fresh signature for each attempt. A signature works for one purchase request only.
Example#
Swift
import StoreKit
// Pass every parameter from one server response, so none is missing.
struct SignedOffer {
let offerID: String
let keyID: String
let nonce: UUID
let signature: Data
let timestamp: Int
}
func buy(_ product: Product, offer: SignedOffer) async {
let option = Product.PurchaseOption.promotionalOffer(offerID: offer.offerID, keyID: offer.keyID, nonce: offer.nonce, signature: offer.signature, timestamp: offer.timestamp)
do {
_ = try await product.purchase(options: [option])
} catch Product.PurchaseError.missingOfferParameters {
print("An offer parameter is missing; request a complete signed offer from the server")
} 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.missingOfferParameters to ErrorCode.invalidPromotionalOfferError (code 34). The SDK assembles the offer parameters itself when you use its promotional offer API, so you see this mostly when you build the option by hand.
Related#
- What does Product.PurchaseError.invalidOfferSignature mean?
- What does Product.PurchaseError.invalidOfferPrice mean?
- What does Product.PurchaseError.invalidOfferIdentifier mean?
Source#
- Apple: Product.PurchaseError.missingOfferParameters
- Apple: promotionalOffer purchase option
- Apple: Generating a signature for promotional offers
- RevenueDot purchases-ios: StoreKitError+Extensions.swift (how the SDK maps StoreKit 2 errors)
Checked: 2026-10-03