StoreKit 2: Transaction.all and Transaction.currentEntitlements return empty for valid non-consumable purchases in production

FB: https://feedbackassistant.apple.com/feedback/22556883

We're seeing a small number of production users where both Transaction.currentEntitlements and Transaction.all return zero transactions for a valid, active, non-refunded non-consumable IAP. This makes it impossible to restore the purchase via any StoreKit 2 API.

Environment:

  • Xcode 26.4 (Build 17E192)
  • iOS 26.4.1
  • Direct call to SK2 Transactions.all & Flutter in_app_purchase package v3.2.3 (uses SK2 on iOS 15+)
  • Non-consumable IAP (one-time purchase)

What we observe:

  • AppStore.sync() triggers but the purchase stream returns 0 transactions
  • Transaction.all returns empty
  • Transaction.currentEntitlements also returns empty
  • User is confirmed on the correct Apple ID
  • Issue reproduces on both iPhone and Mac for the same Apple ID
  • Issue appears to have started recently for users who previously had no problems

Debug log from affected production user:

[2026-04-20T08:50:10.744115Z] init: iapAvailable=true
[2026-04-20T08:50:10.744566Z] init: isPremium=false
[2026-04-20T08:50:10.744567Z] init: triggering silent restorePurchases
[2026-04-20T08:50:45.974566Z] restore: started
[2026-04-20T08:50:45.986848Z] restore: sk2Transactions count=0
[2026-04-20T08:50:45.993004Z] restore: sk2Direct isVerified=false active=null
[2026-04-20T08:50:45.993011Z] restore: sk2Direct inconclusive — falling back to standard restore
[2026-04-20T08:51:16.000851Z] restore: timed out after 30s — fallback isPremium=false
[2026-04-20T08:51:16.000910Z] restore: completed — succeeded=false foundPurchase=false

Unable to reproduce in sandboxTransaction.all works correctly there. Appears specific to production for a small subset of users.

Has anyone else seen this?

Seen this pattern a few times. Transaction.all and Transaction.currentEntitlements both read from a local transaction cache that StoreKit 2 builds by syncing with Apple's servers. If that sync has never completed for the current user on the current device, both streams come back empty even when the purchase still exists server-side.

Users who tend to land in this state:

  • Restored the device from a backup and haven't re-signed into the Apple ID that owns the purchase.
  • Family Sharing participants (not the original buyer). There's been a recurring regression on 26.x where family-shared non-consumables disappear from currentEntitlements after a restore.
  • Changed their Apple ID on the device at some point.

The unblock for all of these is AppStore.sync(). Gate it behind a "Restore Purchases" button (it prompts for Apple ID password, so never call it on launch), and re-read currentEntitlements after it completes. That's the officially documented recovery path for this exact scenario.

If sync() doesn't recover them, the App Store Server API (GET /inApps/v1/history/{transactionId}) is still available server-side and will tell you whether Apple still recognises the purchase at all. That at least narrows it to a device-state issue vs. a server-side one worth escalating to DTS.

Any pattern in the affected users? Recent device restores, family sharing, Apple ID changes?

We're already gating AppStore.sync() behind a Restore Purchases button, so that path is covered.

On the App Store Server API suggestion — we don't store transaction IDs server-side as we have no user account system. The app relies entirely on StoreKit to surface the transaction, which is then verified server-side in the moment but never persisted against a user identity other than in the apps local database. So that avenue isn't available to us.

I have asked the user if they will sign out and sign back in to verify this issue but they so far haven't agreed to do this.

Just to confirm, we are experiencing the exact same issue with a few customers using iOS 26.4.1, where Transaction.currentEntitlements should return their transactions in production but returns none.

We've also observed that this issue occurs in TestFlight environment.

Calling AppStore.sync() does not resolve the issue.

I'm experiencing something similar in production, but I don't have a good enough view into what's happening on the users' devices to say if it's the same issue.

I check Transaction.currentEntitlements and Transaction.all on launch for a valid subscription, and fallback to a nonPremium mode if I fail to find a valid transaction. I've seen a small number of users being bumped out of premium mode even though they have a valid subscription and I've been going round in circles trying to track down the bug.

This seems to have started some time in the last few weeks for me, and I'm not seeing any particular pattern regarding iOS version number, which makes me wonder if this is a server-side App Store issue. I have not made any recent changes to my StoreKit2 code.

First time I've ever had an issue here so I'm not sure of the path of escalation but I appreciate others confirming they're seeing the same issue. I've filed a feedback report but ideally I want to make some more noise about this as I now have multiple users leaving negative reviews as I'm unable to provide them with a solution to a problem that is completely out of my control I've exhausted so many paths now with no clear workaround found.

@JackB321 Yeah, this is very frustrating. The local cached transaction record should be rock solid, but it seems like that's not the case now, which has got me rethinking things.

I already persist an isPremium flag to UserDefaults on successful purchase, so (assuming we don't get some kind of clarity from Apple soon), I'm planning to rely on my flag rather than the transaction record at launch (at least temporarily). It's not really ideal, but my app does authorization checks on the server side anyway, so for my purposes this is a viable option.

Do you have any clarity on whether this bug is still happening today? I can't tell if this was a temporary thing a few weeks ago (and I'm only just seeing the ramifications now) or if it's still an ongoing problem.

@jwcarr Yes it is still happening today. It seems to only really start at the beginning of this week. It's only a very small number of users so debugging is very difficult.

@JackB321 Maybe you could try requesting direct code-level support: https://aninterestingwebsite.com/support/technical/ This would at least get the issue in front of someone who could figure out the problem or escalate it with the relevant team.

@jwcarr I've done that now, awaiting a reply. Thanks. I'll update here with any info.

I confirm that there is a problem when testing on a real device, but there is no problem when testing on a simulator.

@Maria1234 Are you able to reliably recreate the issue? I haven't yet managed to recreate it on a real device or in a simulator.

StoreKit 2: Transaction.all and Transaction.currentEntitlements return empty for valid non-consumable purchases in production
 
 
Q