Apple Developer Forums Post Draft (English)
Title
StoreKit 2 Product.products(for:) returns an empty array for two non-consumable IAPs in TestFlight sandbox
Post
Hello,
I am troubleshooting a StoreKit 2 product-loading issue in the TestFlight sandbox and would appreciate any advice.
Issue
When the iOS app is installed from TestFlight (Build 4), Product.products(for:) is called for two non-consumable In-App Purchases. The call doesn't throw an error, but it consistently returns an empty array, so no products appear in the purchase UI.
products = try await Product.products(for: [
"com.shidan.qieting.plus.trial.7day",
"com.shidan.qieting.plus.lifetime"
]).sorted { $0.id < $1.id }
The products are:
Product ID
Type
Price
App Store Connect status
com.shidan.qieting.plus.trial.7day
Non-consumable
Tier 0 / US$0.00
Ready to Submit
com.shidan.qieting.plus.lifetime
Non-consumable
US$5.99
Ready to Submit
Diagnostic log
On cold launch of the TestFlight app, the diagnostic log shows:
2026-09-03T08:12:08Z [settings] plus products loaded: trialAvailable=false, lifetimeAvailable=false
The same empty result occurs again when opening the purchase page. There is no StoreKit exception and no purchase-flow error.
System-level sandbox verification
To rule out the app UI and the app's product-loading code, I created a Sandbox Apple Account in the same developer team and used iOS Settings > Developer > Sandbox Apple Account > Manage > Test Transactions.
Bundle ID: com.shidan.qieting
Product ID: com.shidan.qieting.plus.lifetime
The system reports that the provided product ID or bundle ID is invalid. This happens before the app's purchase UI or Product.products(for:) result is involved, so the sandbox does not appear to recognize this bundle/product pair.
Checks completed
The Product IDs in code exactly match the Product IDs in App Store Connect.
The Release bundle identifier exactly matches the App Store Connect app record: com.shidan.qieting.
The App ID is explicit, not wildcard.
In-App Purchase is enabled for the App ID in Certificates, Identifiers & Profiles. The Xcode target also declares the capability, and Xcode Cloud uses automatic signing.
The TestFlight build is an archive. The shared scheme's ArchiveAction has no StoreKit Configuration file; the local .storekit file is only used by Xcode Run/Test actions and doesn't apply to the archived/TestFlight app.
Both products have a price, availability in all 175 App Store storefronts, and Simplified Chinese, Traditional Chinese, and English localizations.
The last IAP metadata change was more than 48 hours ago.
The Paid Apps Agreement, tax information, and banking information are active/in use.
Neither the app nor the IAPs have been submitted for review. My understanding is that submission isn't required to fetch products in the TestFlight sandbox.
EU Digital Services Act (DSA) trader compliance is still under review. Apple describes this as EU App Store product-page trader information, and TestFlight-only distribution isn't App Store trader distribution; therefore, it shouldn't affect TestFlight sandbox product retrieval or Test Transactions.
Question
With all of the above confirmed, what App Store Connect, sandbox, signing, or TestFlight configuration might still cause both Product.products(for:) and the system-level Test Transactions tool to reject these product IDs?
Has anyone encountered a case where the Product IDs, bundle ID, pricing, localizations, and worldwide availability were correct, but the TestFlight sandbox still treated the bundle/product pair as invalid? Is there a known sandbox propagation or backend issue, or another diagnostic step that can identify the missing association?
I can provide redacted screenshots of the App Store Connect product configuration and the Test Transactions error if helpful. Thank you.
Posting notes
Do not post API private keys, full banking/tax information, private team configuration, or personal address details.
Keep the Product IDs, Bundle ID, code snippet, and diagnostic timestamp unchanged when posting.