Transaction.finish() doesn't clear a transaction on iOS 27 beta 5 — worked correctly through beta 4 — every repeat purchase after the first replays the same transaction with no confirmation sheet and no charge.
StoreKit.Transaction.finish() does not clear a transaction on iOS 27 beta 5. The transaction remains in Transaction.unfinished indefinitely, and every subsequent Product.purchase() call for that product returns the same stale transaction instead of starting a new purchase — with no confirmation sheet, no charge, and no way for the app to tell it apart from a genuine purchase.
Because the replayed result is .success carrying a VerificationResult that verifies normally, an app has no supported signal that nothing was bought. The only distinguishing traits are that the id and purchaseDate are unchanged and the call returns in ~10ms instead of making a server round-trip.
Consequence: a consumable product can be purchased exactly once per device. Every later attempt silently no-ops while appearing to succeed.
Steps to Reproduce
On a device running iOS 27 beta 5, sign in to a newly created Sandbox Apple Account (Settings → Apps → App Store → Sandbox Account) with no prior purchase history.
Install and launch a development build of an app offering a consumable IAP.
Confirm Transaction.unfinished is empty.
Purchase the consumable. The confirmation sheet appears and the purchase completes normally.
await transaction.finish() on the returned transaction.
Enumerate Transaction.unfinished again.
Purchase the same consumable a second time.
Expected Results
Step 6: Transaction.unfinished is empty — the transaction was finished.
Step 7: a confirmation sheet appears and a new transaction is created, with a new id and a current purchaseDate.
Actual Results
Step 6: the just-finished transaction is still listed in Transaction.unfinished.
Step 7: no confirmation sheet appears. purchase() returns .success in ~0.01s carrying the same transaction — identical id and identical purchaseDate — and nothing is charged. This repeats indefinitely.
Re-fetching the transaction from Transaction.unfinished and calling finish() on that instance does not clear it either, so there is no app-side way to drain the queue.
Diagnostic Log
Virgin sandbox account, empty queue, three consecutive taps on one product:
unfinished before tip.small: []
purchase() returned after 18.10s
tip.small: id=2000001221113013 purchaseDate=2026-08-13 22:36:26 +0000
--- await transaction.finish() ---
unfinished after finishing 2000001221113013: [small#2000001221113013]
unfinished before tip.small: [small#2000001221113013]
purchase() returned after 0.01s
tip.small: id=2000001221113013 purchaseDate=2026-08-13 22:36:26 +0000
unfinished before tip.small: [small#2000001221113013]
purchase() returned after 0.01s
tip.small: id=2000001221113013 purchaseDate=2026-08-13 22:36:26 +0000
The first call is a genuine purchase (18s round-trip, sheet shown). The transaction survives its own finish(). Calls two and three are replays of it.
Notes
Not reproducible against a local .storekit configuration in the Simulator, which always presents the confirmation sheet. Requires Apple's sandbox.
Also reproduces on a TestFlight build billed to a real Apple ID, where it is worse: TestFlight purchase history cannot be reset, so the affected products stay permanently stuck for that account. It survives deleting and reinstalling the app, and a device reboot.
Possibly the same underlying issue as the unanswered report at https://developer.apple.com/forums/thread/808648 (iOS 26/18, Nov 2025).
Configuration
Device: iPhone 16 Pro Max
OS: iOS 27 beta 5
Products: consumable in-app purchases
API: StoreKit 2 (Product.purchase(), Transaction.finish(), Transaction.unfinished)
2
0
70