---
title: "What does Product.PurchaseError.invalidQuantity mean?"
description: "Product.PurchaseError.invalidQuantity means the quantity passed to a StoreKit 2 purchase is not valid. Quantity applies to consumables and non-renewing subscriptions only."
url: https://revenuedot.app/docs/errors/storekit-purchase-error-invalid-quantity
---

# What does Product.PurchaseError.invalidQuantity mean?

Product.PurchaseError.invalidQuantity means the quantity you passed to `purchase(options:)` is not valid.

## Quick facts

| | |
|---|---|
| Error | `Product.PurchaseError.invalidQuantity` |
| 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 quantity to purchase is invalid. |

## Cause

- The `.quantity(_:)` purchase option sets how many items the customer buys. Apple says the quantity applies to consumable In-App Purchases and non-renewing subscriptions ([PurchaseOption.quantity](https://developer.apple.com/documentation/storekit/product/purchaseoption/quantity%28_:%29)).
- A quantity for a product of another type, or a value outside what the App Store accepts, is not a valid quantity. Apple does not publish the accepted range on the case page.
- The error comes from the arguments your code passes, so it is reproducible and not a store outage.

## Fix

1. Remove the `.quantity` option unless the product is a consumable or a non-renewing subscription.
2. Pass a whole number of at least 1, and keep it small. Log the value you send.
3. Check the product's type in App Store Connect against what your code assumes.
4. Test the purchase in the sandbox or a StoreKit configuration file before you ship.

## Example

```swift
import StoreKit

// Quantity is for consumables and non-renewing subscriptions only; guard the value before you pass it.
func buy(_ product: Product, quantity: Int) async {
    guard quantity >= 1 else { return }
    do {
        let result = try await product.purchase(options: [.quantity(quantity)])
        print("Result: \(result)")
    } catch Product.PurchaseError.invalidQuantity {
        print("The App Store rejected quantity \(quantity) for \(product.id)")
    } 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.invalidQuantity` to `ErrorCode.storeProblemError` (code 2). The SDK's own purchase API does not expose a quantity, so this error normally appears only when your code calls StoreKit directly. See [what storeProblemError means](https://revenuedot.app/docs/errors/sdk-store-problem-error.md).

## Related

- [What does storeProblemError (code 2) mean in the purchases SDK?](https://revenuedot.app/docs/errors/sdk-store-problem-error.md)
- [What does Product.PurchaseError.productUnavailable mean?](https://revenuedot.app/docs/errors/storekit-purchase-error-product-unavailable.md)
- [What does Product.PurchaseError.purchaseNotAllowed mean?](https://revenuedot.app/docs/errors/storekit-purchase-error-purchase-not-allowed.md)

## Source

- [Apple: Product.PurchaseError.invalidQuantity](https://developer.apple.com/documentation/storekit/product/purchaseerror/invalidquantity)
- [Apple: Product.PurchaseError](https://developer.apple.com/documentation/storekit/product/purchaseerror)
- [RevenueDot purchases-ios: StoreKitError+Extensions.swift (how the SDK maps StoreKit 2 errors)](https://github.com/revenuedot/purchases-ios/blob/revenuedot/main-patches/Sources/Error%20Handling/StoreKitError%2BExtensions.swift)

Checked: 2026-10-03
