Skip to content

Tracking: Apple 12-month commitment (:monthly) billing plans unavailable in KMP — bundled libRevenueCat.a is built with Swift 6.1.2 #934

Description

@danego61
  • I have updated Purchases SDK to the latest version

  • I have read the Contribution Guidelines

  • I have searched the Community

  • I have read docs.revenuecat.com

  • I have searched for existing GitHub issues

    Describe the bug

    Apple's new "Monthly Subscriptions with a 12-Month Commitment" billing plans (<product_id>:monthly products, docs) never appear in offerings
    on iOS when using purchases-kmp. Offerings only return the standard packages (e.g. $rc_annual, $rc_weekly); the package configured with the :monthly product is silently dropped.

    I'm aware the docs say "Available in the native iOS SDK in versions 5.76.0+, support in the hybrid SDKs is coming soon" — purchases-kmp 3.3.0 already bundles purchases-ios 5.80.3 (which satisfies 5.76+), so I dug into why
    it still doesn't work and am filing this as a tracking issue with the root cause identified, since I couldn't find an existing one.

    Root cause: the installment/billing-plan code path in purchases-ios is gated behind a compile-time check, and the pre-compiled static library shipped inside the KMP klibs is built with an older Swift toolchain, so that code
    path is compiled out entirely:

    1. The code gate. In purchases-ios (ProductsFetcherSK2.swift, also InstallmentsInfoFactory.swift), all billing-plan handling is wrapped in:

      // Billing plans were introduced with Xcode 26.5, which shipped with Swift version 6.3.2.
      #if compiler(>=6.3.2)
    2. The shipped binary. The libRevenueCat.a inside purchases-kmp-kn-core-iosarm64-3.3.0-cinterop-RevenueCat.klib (verified against Maven Central's published checksum, sha256
      eaaf9204869cffb554f39207456557f9417ecae69fdedeabc34202d86d6cfdc6) is stamped with Apple Swift version 6.1.2 (464 occurrences via strings, no other version). A symbol lookup via nm confirms there are zero references to
      StoreKit's Product.SubscriptionInfo.PricingTerms — the gated code physically doesn't exist in the binary. (RevenueCat's own ungated RCInstallmentsInfo / RCBillingPlanType types are present, so the cinterop API surface
      exists but can never be populated on the Apple side.)

    3. The CI configuration. .circleci/config.yml builds and publishes the KMP artifacts with the xcode16 executor (xcode: 16.4.0 → Swift 6.1.2), including the publish job.

    Since 6.1.2 < 6.3.2, populateSK2CompoundProductsIfSupported compiles to a no-op, the :monthly StoreKit product is never created, and OfferingsFactory.createOffering silently drops the package via compactMap. Using Xcode
    26.5 locally does not help, because the consuming app links the pre-compiled .klib artifact from Maven Central.

    I do realize the Xcode 16.4.0 pin is deliberate — the comment above the xcode16 executor explains it (consuming-app minimum Xcode version / RevenueCatUI in 3.0.1 references private SwiftUI symbols and SwiftUICore; iOS host link fails with "not an allowed client of SwiftUICore" + undefined SwiftUI internal symbols #859, Kotlin/Native's supported Xcode versions, and CircleCI's image retention policy).
    So this is likely non-trivial to fix and may need to wait for Kotlin/Native to support Xcode 26.5, or a dual-artifact strategy. Filing this so there's a tracking issue for KMP users, since this feature cannot be worked around on
    the app side.

    Environment

    1. Platform: iOS (Kotlin Multiplatform)
    2. SDK version: purchases-kmp 3.3.0 (bundles purchases-ios 5.80.3)
    3. OS version: iOS 26.4+
    4. IDE: Android Studio & Xcode
    5. Xcode version (local): 26.5
    6. Device and/or emulator/simulator:
      • Device
      • Emulator/simulator
    7. Environment:
      • Sandbox
      • TestFlight
      • Production
    8. How widespread is the issue: 100% of KMP iOS apps trying to use Apple installment/commitment billing plans.

    Steps to reproduce, with expected vs. actual behavior

    1. In App Store Connect, add a "Monthly with 12-Month Commitment" billing plan to an annual subscription product.
    2. In the RevenueCat dashboard, create the :monthly product (12-months-commitment option enabled) and attach it to a package in the current offering.
    3. In a KMP app on an iOS 26.4+ device, call Purchases.sharedInstance.awaitOfferings() (or getOfferings).

    Expected: the offering contains the package with the :monthly installment product, with populated installments info.

    Actual: the package is missing from availablePackages; only the base packages are returned.

    Suggested fix

    Build and publish the KMP iOS artifacts (the static Swift library embedded in the Kotlin/Native klibs) with Xcode 26.5+ / Swift 6.3.2+, once the constraints above allow it. Happy to provide any additional info or test a snapshot
    build.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions