flutter-stripe / flutter_stripe

Flutter SDK for Stripe.
https://pub.dev/packages/flutter_stripe
940 stars 518 forks source link

`lateinit property configuration has not been initialized` coming from `GooglePayLauncherFragment.java` #1282

Open NunoOliveiraP opened 1 year ago

NunoOliveiraP commented 1 year ago

Describe the bug We've been seeing a fair amount of Crashlytics error logs coming from what we imagine is one of the packages you rely on for this plugin.

There error is lateinit property configuration has not been initialized coming from GooglePayLauncherFragment.java:29. These errors seem to happen right at startup and likely after the app was launched from a notification interaction. We believe this is the case since the only local logs we can find before the error is thrown are session_start events from Firebase Analytics or the details of a background notification we just received (sometimes we see no logs at all).

All we have is the stacktrace and the information described above. Are you aware of anything that could be the cause for this?

To Reproduce We are not aware of how to reproduce this.

Expected behavior This error shouldn't happen since we have no interaction with any Stripe-related functionality or code at startup.

Smartphone / tablet

Additional context Stacktrace:

Fatal Exception: R9.B: lateinit property configuration has not been initialized
       at com.reactnativestripesdk.GooglePayLauncherFragment.onViewCreated(GooglePayLauncherFragment.java:29)
       at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:4)
       at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:6)
       at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:3)
       at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:30)
       at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:27)
       at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:9)
       at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:11)
       at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:4)
       at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:20)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1510)
       at android.app.Activity.performStart(Activity.java:8616)
       at android.app.ActivityThread.handleStartActivity(ActivityThread.java:4204)
       at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
       at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2574)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8757)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
jamesblasco commented 1 year ago

Hi @NunoOliveiraP, could you clarify it at any point you allow users to pay using the GooglePayButton?

It looks like the app looses the state at some point, the system restores the fragment automatically but we do not restore the local variables inside the fragment. I will create an issue in the Stripe React Native repository which whom we share the native layer

NunoOliveiraP commented 1 year ago

Hi @NunoOliveiraP, could you clarify it at any point you allow users to pay using the GooglePayButton?

It looks like the app looses the state at some point, the system restores the fragment automatically but we do not restore the local variables inside the fragment. I will create an issue in the Stripe React Native repository which whom we share the native layer

Hi @jamesblasco, thanks for the reply! We do use the Google Pay button on one of our screens... Removing it won't be an option, but the error does not seem to affect the user experience as we haven't heard of any bugs from our users. It's mostly just a nuisance since it adds noise to our Crashlytics statistics and seems impossible to catch...

jamesblasco commented 1 year ago

Thanks @NunoOliveiraP, I have pointed to the official Stripe team to fix in in the respective repo. As soon as it is fixed there we will update it on our side

emilysmithson commented 11 months ago

We are seeing the exact same issue in crashlytics

ibrahimtelman commented 7 months ago

Is there any update on this issue? We have the same issue in Crashlytics.

remonh87 commented 6 months ago

We are depending on the Stripe dev team to fix it. Until then there is nothing we can do.

DavidEcclesPH commented 5 months ago

@remonh87 @jamesblasco I have recreated by exiting the app while google pay is launching (what crazy users do this?!). Coming back to the app via the app switcher, google pay is presented over the app switcher, but everything dismisses straight away when google pay is dismissed. If there is a way we could stop google pay launching, we could call this when the app moves to the background? I had a look through the package but couldn't find a way to do this, would that be something you would consider adding? At the moment everything is behind the scenes after calling confirmPlatformPayPaymentIntent or confirmPlatformPaySetupIntent. Thanks!

kissbudai commented 4 months ago

It can be reproduced constantly if the 'Don't keep activities' is enabled.

Stacktrace:

kotlin.UninitializedPropertyAccessException: lateinit property configuration has not been initialized
    at com.reactnativestripesdk.GooglePayLauncherFragment.onViewCreated(GooglePayLauncherFragment.kt:41)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3147)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:588)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:272)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:114)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1455)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3034)
    at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2952)
    at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263)
    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:350)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1433)
    at android.app.Activity.performStart(Activity.java:7923)
    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3332)
    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
    at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:224)
    at android.app.ActivityThread.main(ActivityThread.java:7562)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

We face the same issue and the number of occurrences is quite high.

DavidEcclesPH commented 2 weeks ago

@kissbudai are you still experiencing this issue? How do you reproduce the issue, I'm not sure what you mean by enabling 'Don't keep activities'? thanks! Update: I found what you mean, developer setting to simulate OS killing the activity 👍 Are you still experiencing the crash?

kissbudai commented 2 weeks ago

@DavidEcclesPH yes, we are still facing this, for a lot of users.

When the payment modal is presented, in the background if something kills the Activity (this happens controllably with the Don't keep activities) then there is no proper state restoration and a lateinit field is not initialized. The big issue with this is that this is an actual crash, the app will force-close for the users.

I also posted this on the react native package as if I understood correctly the flutter package wraps that one, but no response so far.

It's quite a critical issue in my opinion, to which I couldn't find a reasonable workaround.

kissbudai commented 2 weeks ago

@DavidEcclesPH What do you mean by the issue was closed? It is still open, only a related issue was closed. The underlying issue from the react-native SDK: https://github.com/stripe/stripe-react-native/issues/1425.

I don't know if not launching googlepay would do the trick or do anything at all. At this point, we're already in the payment flow. The GooglePayLauncherFragment initializes and launches it. During this, the activity behind (which holds the GooglePayLauncherFragment` gets killed), and then that lateinit field will not be initialized again. The strange thing is that I could only reproduce this by the 'Don't keep activities' developer options, but at the same time, we're seeing a large number of crashes and it's unlikely that users have such settings. Now either they are doing something heavy with other applications and the system needs to free up memory or there is something else.

It would be great to have a solution for this or at least a workaround, but unfortunately, I think this needs to be addressed in the react-native SDK and there no-one replied.

DavidEcclesPH commented 2 weeks ago

@kissbudai you're quite right, I just removed that comment. I tested a few times yesterday on the latest version 11.1.0 with 'don't keep activities' on and didn't see any crashes. I also found an old device (very old android 8.1) that the issue could be reproduced by going to the background while googlepay launches, which users might do as it took a long time to launch on that device. If you changed to another app, then back, googlepay was presented over the 'app switcher' and crashed when relaunching the app making payment. However this is also not happening in the latest version, so I'm optimistic that the latest version has at least improved things 🤞 We will soon see from the crash logs!

favazHF commented 1 week ago

Hi, any WA or update how to prevent this crash? thanks!

leewrigg commented 4 days ago

I am still seeing this issue on the latest version of the package. Following @kissbudai's instructions I was able to reproduce this easily -

  1. Enable Don't keep activities in the phone's Developer Options settings.
  2. Open your app and view the Google Pay sheet before minimising the app (you can pay it, close the sheet, or simply leave it open).
  3. Minimise your app (with 'don't keep activities' enabled, this kills the activity straight away. Without this option, you'd need to leave it in the background for a while I guess.)
  4. Bring the app back into the foreground. For me, it crashes at this point every time.
anvemonta commented 16 hours ago

This is becoming a big problem for us as well and its incredibly hard to find a work around, even though it can be consistently reproduced. I doubt users have Don't keep activitiesenabled in their phone's Developer Options settings so I'm assuming the OS is needing to free up some space and as a result is losing the fragment state.

Anyhow, has anyone found an update or a workaround?