Skip to main content
Question

Upgrade/Downgrade failing with GoogleProductChangeInfo in RevenueCat Flutter v9.15.1

  • March 25, 2026
  • 3 replies
  • 38 views

Forum|alt.badge.img

Hi everyone,

I'm using RevenueCat Flutter SDK v9.15.1 and having issues with subscription upgrades and downgrades on Android (Google Play).

Setup:
- Single subscription ID: `pro_access`
- Base plans: `starter_monthly`, `starter_yearly`, `premium_monthly`, `premium_yearly`, `professional_monthly`, `professional_yearly`
 

if (Platform.isAndroid && oldProductId != null && oldProductId.isNotEmpty) {
params = PurchaseParams.storeProduct(
newProduct,
googleProductChangeInfo: GoogleProductChangeInfo(
oldProductId,
prorationMode: GoogleProrationMode.immediateWithTimeProration,
),
);
} else {
params = PurchaseParams.storeProduct(newProduct);
}

Questions:

1. Should `oldProductId` be passed as `pro_access:starter_monthly` or just `starter_monthly`?
2. Is `GoogleReplacementMode.deferred` the correct mode for downgrades?
3. Is there anything specific to v9.15.1 that affects `GoogleProductChangeInfo`?

Google Play returns a generic error and RevenueCat logs a replacement mode error. Any help appreciated!

3 replies

alejandra-wetsch
RevenueCat Staff
Forum|alt.badge.img+6

Hey ​@elexoft-team-a7d3ed

Thank you for reaching out!

Should `oldProductId` be passed as `pro_access:starter_monthly` or just `starter_monthly`?

In this case, you should use the full product ID pro_access:starter_monthly

Is `GoogleReplacementMode.deferred` the correct mode for downgrades?

For downgrades, GoogleReplacementMode.deferred is the correct replacement mode to use. You can check examples of which replacement modes to use in the official Google Play documentation here.

Is there anything specific to v9.15.1 that affects `GoogleProductChangeInfo`?

Nothing specific affecting GoogleProductChangeInfo in this version.

 

If, after using the correct GoogleReplacementMode and the correct productID, you’re still experiencing issues, please share some debug logs, from which products you’re upgrading/downgrading to and from, and screenshots of their configuration in Google Play. Given that this may be private information, you could also create a support ticket to share this information with us.

I hope this helps!


Forum|alt.badge.img

Not working; currently I have a Subscription with 6 base plans.
If I include proration mode deferred on change a subscription (From started-yearly to premium-monthly) it won’t work if I leave proration mode null, with old product id (except base plan e.g: pro_access:starter-yearly → pro_access) then it works and open google payment sheet with information like payment will be deducted at the end of current subscription expiry date and user is now switched to new plan which should technically be activated when the current plan expires.


Tarek
RevenueCat Staff
Forum|alt.badge.img+4
  • RevenueCat Staff
  • April 3, 2026

Hey ​@elexoft-team-a7d3ed,

 

Thanks for sharing this, it's very helpful. What you discovered is actually the correct behavior. Here's why:

I think there was a misunderstanding, I'm sorry about that. Your 6 base plans all live under one subscription (pro_access), so switching between them is a within-product base plan change, not a cross-product upgrade/downgrade. Google Play treats these differently.

For same-product base plan switches:

  • oldProductId should be just pro_access in this case (not pro_access:starter_yearly)
  • Replacement mode should be omitted: Google Play ignores SDK-specified modes for within-product changes and uses whatever you've configured in the Google Play Console instead
  • That's exactly why the last version worked. The deferred mode was failing because Google rejects SDK-specified replacement modes for this type of change.

What to do:

  1. Configure your desired replacement behavior for base plan changes directly in the Google Play Console (under your pro_access subscription settings)
  2. In code, pass only the subscription ID with no replacement mode:
params = PurchaseParams.storeProduct(
 newProduct,
 googleProductChangeInfo: GoogleProductChangeInfo('pro_access'),
);


I hope that clears things up, let me know if there's anything else we can do!

 

Best,