RevenueCat / RevenueCat/react-native-purchases

Build fails with Xcode 26.3+ — TestStoreProduct, TestStoreProductDiscount, TestStoreTransaction not found in scope

Open
#1,817 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
1.2k
Forks
117
Avg merge
14h 40m
Merged PRs (30d)
40

Description

Describe the bug
Building with Xcode 26.3 or 26.4 fails due to Swift compilation errors in PurchasesHybridCommon. The iOS 26 SDK appears to have removed or renamed StoreKit types and changed the signature of Product.PurchaseOption. EAS builds fail on EAS servers and on local builds.

Errors (from RevenueCat/Sources/Purchasing/OfferingsManager.swift)

  cannot find 'TestStoreProduct' in scope
  cannot find type 'TestStoreProductDiscount' in scope
  cannot find type 'TestStoreProduct' in scope
  cannot find 'TestStoreTransaction' in scope
  cannot convert value of type '[String : String]?' to expected argument type
  'Set<Product.PurchaseOption>'
  extra argument 'completion' in call
  type of expression is ambiguous without a type annotation
  1. Platform: iOS
  2. SDK version: 10.3.0
  3. OS version: iOS 26
  4. Xcode/Android Studio version: Xcode 26.3 (local), Xcode 26.4 (EAS cloud build)
  5. React Native version: 0.81.5
  6. SDK installation: CocoaPods 1.16.2

Additional context

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/OfferingsManager.swift:435:24)

  433 |                 // all dummy yearly subscriptions have a 1-week free trial
  434 |                 guard productType.period?.unit == .year else { return nil }
> 435 |                 return TestStoreProductDiscount(
      |                        ^ cannot find 'TestStoreProductDiscount' in scope
  436 |                     identifier: "intro",
  437 |                     price: 0,
  438 |                     localizedPriceString: "$0.00",

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/OfferingsManager.swift:446:31)

  444 |             }()
  445 |
> 446 |             let testProduct = TestStoreProduct(
      |                               ^ cannot find 'TestStoreProduct' in scope
  447 |                 localizedTitle: "PRO \(productType.type)",
  448 |                 price: Decimal(productType.price),
  449 |                 currencyCode: "USD",

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/OfferingsManager.swift:431:39)

  429 |                                                               productIdentifier: identifier)
  430 |
> 431 |             let introductoryDiscount: TestStoreProductDiscount? = {
      |                                       ^ cannot find type 'TestStoreProductDiscount' in scope
  432 |                 // To allow introductory offers in UI Preview mode,
  433 |                 // all dummy yearly subscriptions have a 1-week free trial
  434 |                 guard productType.period?.unit == .year else { return nil }

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/OfferingsManager.swift:427:43)

  425 |     ) -> Set<StoreProduct> {
  426 |         let packagesByProductID = response.packages.dictionaryAllowingDuplicateKeys { $0.platformProductIdentifier }
> 427 |         let products = productIdentifiers.map { identifier -> StoreProduct in
      |                                           ^ type of expression is ambiguous without a type annotation
  428 |             let productType = self.inferredPreviewProductType(from: packagesByProductID[identifier],
  429 |                                                               productIdentifier: identifier)
  430 |

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/SimulatedStore/SimulatedStorePurchaseHandler.swift:20:28)

  18 |
  19 |     @MainActor
> 20 |     func purchase(product: TestStoreProduct) async -> TestPurchaseResult
     |                            ^ cannot find type 'TestStoreProduct' in scope
  21 |
  22 | }
  23 |

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/SimulatedStore/SimulatedStoreProduct.swift:16:44)

  14 | import Foundation
  15 |
> 16 | internal typealias SimulatedStoreProduct = TestStoreProduct
     |                                            ^ cannot find type 'TestStoreProduct' in scope
  17 | internal typealias SimulatedStoreProductDiscount = TestStoreProductDiscount
  18 |

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/StoreKitAbstractions/StoreProduct.swift:354:36)

  352 |
  353 |     /// Returns the `TestStoreProduct` if this `StoreProduct` represents a `TestStoreProduct`.
> 354 |     internal var testStoreProduct: TestStoreProduct? {
      |                                    ^ cannot find type 'TestStoreProduct' in scope
  355 |         return self.product as? TestStoreProduct
  356 |     }
  357 |

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift:2142:105)

  2140 |                         completion: @escaping PurchaseCompletedBlock) {
  2141 |         if self.systemInfo.isSimulatedStoreAPIKey {
> 2142 |             self.purchase(simulatedStoreProduct: simulatedStoreProduct, metadata: metadata, completion: completion)
       |                                                                                                         ^ extra argument 'completion' in call
  2143 |         } else {
  2144 |             self.handleTestProductNotAvailableForPurchase(completion)
  2145 |         }

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift:2142:83)

  2140 |                         completion: @escaping PurchaseCompletedBlock) {
  2141 |         if self.systemInfo.isSimulatedStoreAPIKey {
> 2142 |             self.purchase(simulatedStoreProduct: simulatedStoreProduct, metadata: metadata, completion: completion)
       |                                                                                   ^ cannot convert value of type '[String : String]?' to expected argument type 'Set<Product.PurchaseOption>'
  2143 |         } else {
  2144 |             self.handleTestProductNotAvailableForPurchase(completion)
  2145 |         }

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/SimulatedStore/SimulatedStoreProduct.swift:17:52)

  15 |
  16 | internal typealias SimulatedStoreProduct = TestStoreProduct
> 17 | internal typealias SimulatedStoreProductDiscount = TestStoreProductDiscount
     |                                                    ^ cannot find type 'TestStoreProductDiscount' in scope
  18 |

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/SimulatedStore/SimulatedStorePurchaseHandler.swift:48:28)

  46 |     }
  47 |
> 48 |     func purchase(product: TestStoreProduct) async -> TestPurchaseResult {
     |                            ^ cannot find type 'TestStoreProduct' in scope
  49 |         guard !self.purchaseInProgress else {
  50 |             return .failure(ErrorUtils.operationAlreadyInProgressError())
  51 |         }

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/SimulatedStore/SimulatedStorePurchaseHandler.swift:83:50)

  81 |     }
  82 |
> 83 |     private func createStoreTransaction(product: TestStoreProduct) async -> StoreTransaction {
     |                                                  ^ cannot find type 'TestStoreProduct' in scope
  84 |         let purchaseDate = self.dateProvider.now()
  85 |         let purchaseToken = "test_\(purchaseDate.millisecondsSince1970)_\(UUID().uuidString)"
  86 |         let storefront = await Storefront.currentStorefront

[RUN_FASTLANE]
❌  (ios/Pods/RevenueCat/Sources/Purchasing/StoreKitAbstractions/StoreTransaction.swift:155:13)

  153 |     ) {
  154 |         self.init(
> 155 |             TestStoreTransaction(
      |             ^ cannot find 'TestStoreTransaction' in scope
  156 |                 productIdentifier: productIdentifier,
  157 |                 purchaseDate: purchaseDate,
  158 |                 transactionIdentifier: transactionIdentifier,

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure with Xcode 26.3 or 26.4, then inspect the reported files: Purchasing/OfferingsManager.swift, Purchasing/SimulatedStore/SimulatedStoreProduct.swift, SimulatedStorePurchaseHandler.swift, StoreKitAbstractions/StoreProduct.swift and StoreTransaction.swift, and Purchases/PurchasesOrchestrator.swift. Trace the missing StoreKit test types and changed purchase signature. Done means the iOS build completes without these Swift compilation errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, react-native, swift
Domain
build-system, mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.