purchases-android icon indicating copy to clipboard operation
purchases-android copied to clipboard

Fatal Exception: kotlin.UninitializedPropertyAccessException; There is no singleton instance. Make sure you configure Purchases before trying to get the default instance. More info here: https://errors.rev.cat/configuring-sdk

Open Psihey opened this issue 4 months ago • 10 comments

Describe the bug Hi! We've updated the RevenueCat version from 8.21.0 to 9.1.1 and ran into a crash. We haven’t made any changes to our RevenueCat wrapper code — we just bumped the version. We are using paywall version 2.

  1. Platform: Android

  2. SDK version:: implementation("com.revenuecat.purchases:purchases:9.1.1") implementation("com.revenuecat.purchases:purchases-ui:9.1.1")

  3. OS version: CompileSdkVersion - 35 KotlinVersion - 2.0

  4. Stacktraces Fatal Exception: kotlin.UninitializedPropertyAccessException There is no singleton instance. Make sure you configure Purchases before trying to get the default instance. More info here: https://errors.rev.cat/configuring-sdk Fatal Exception: kotlin.UninitializedPropertyAccessException: There is no singleton instance. Make sure you configure Purchases before trying to get the default instance. More info here: https://errors.rev.cat/configuring-sdk at com.revenuecat.purchases.Purchases$Companion.getSharedInstance(Purchases.kt:1004) at com.revenuecat.purchases.ui.revenuecatui.data.PurchasesImpl.(PurchasesType.kt:51) at com.revenuecat.purchases.ui.revenuecatui.data.PaywallViewModelImpl.(PaywallViewModel.kt:76) at com.revenuecat.purchases.ui.revenuecatui.data.PaywallViewModelFactory.create(PaywallViewModelFactory.kt:20) at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.android.kt:190) at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.android.kt:195) at androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel(ViewModelProviderImpl.android.kt:34) at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release(ViewModelProviderImpl.kt:60) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.android.kt:110) at androidx.lifecycle.viewmodel.compose.ViewModelKt__ViewModelKt.get(ViewModel.kt:170) at androidx.lifecycle.viewmodel.compose.ViewModelKt.get(:1) at androidx.lifecycle.viewmodel.compose.ViewModelKt__ViewModelKt.viewModel(ViewModel.kt:106) at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(:1) at com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.getPaywallViewModel(InternalPaywall.kt:377) at com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.InternalPaywall(InternalPaywall.kt:62) at com.revenuecat.purchases.ui.revenuecatui.PaywallKt.Paywall(Paywall.kt:11) at com.revenuecat.purchases.ui.revenuecatui.activity.PaywallActivity$onCreate$1$1$1.invoke(PaywallActivity.kt:137) at com.revenuecat.purchases.ui.revenuecatui.activity.PaywallActivity$onCreate$1$1$1.invoke(PaywallActivity.kt:129) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.material3.ScaffoldKt$ScaffoldLayout$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:261) at androidx.compose.material3.ScaffoldKt$ScaffoldLayout$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:238) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)

5.Operating systems: 74% - Android 15 26% - Android 14

Psihey avatar Aug 01 '25 10:08 Psihey

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

RCGitBot avatar Aug 01 '25 10:08 RCGitBot

Hey @Psihey , thanks for reporting!

I have passed this onto our team - in the meantime, are you able to share some code snippets around the way you are configuring the SDK and making the call to purchases?

Also, does this happen all the time and on a fresh app launch? Or after a while and intermittently (e.g when switching accounts).

GuilhermeMota93 avatar Aug 05 '25 16:08 GuilhermeMota93

@GuilhermeMota93 Hi! Thanks for your reply! The crashes happened during the first second of the user's session.

Configuring the SDK :

Purchases.configure(
                PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_KEY)
                    .appUserID(userId)
                    .build()
            )            

For call to purchases, we are using: private val paywallActivityLauncher: PaywallActivityLauncher = PaywallActivityLauncher(caller, this) together with paywallActivityLauncher.launchIfNeeded()

Crash happens in production, and we cannot reproduce it in the testing environment.

Psihey avatar Aug 11 '25 08:08 Psihey

Hey @Psihey,

Thanks for those extra details - so, as also the logs indicate, that crash happens when a call to the Purchases singleton happens and the SDK is not correctly configured. You mentioned no code changes on your side apart from the SDK bump, so I would like to ask for a bit more context around the code initialisation and usage if that's okay.

Before launching the paywall, could you try and check Purchases.isConfigured and log what happens there? More context here.

Also, can you confirm that no RevenueCat-related code runs before your Purchases.configure(...) call, and that production uses the same init sequence as test does?

If RevenueCat debug logs aren’t already enabled, could you enable them via https://www.revenuecat.com/docs/test-and-launch/debugging, and share a .txt file with logs from app launch to the crash please?

Lastly, and if possible, a short video of the flow leading to the crash and one when it work as expected would also help us understand the timing of it.

Thanks!

GuilhermeMota93 avatar Aug 11 '25 09:08 GuilhermeMota93

@GuilhermeMota93 Thanks, we’ll check and get back to you!

Psihey avatar Aug 11 '25 09:08 Psihey

I also noticed this crash in my Flutter app on Android production (can't reproduce in staging). However it happens at the very beginning when the App is being opened. This is all the code that's being called during that time:

await Purchases.setLogLevel(LogLevel.debug);
PurchasesConfiguration configuration = PurchasesConfiguration("API_KEY");
await Purchases.configure(configuration);
Purchases.addCustomerInfoUpdateListener((customer) { ... })

I'm not using Paywall, so I doubt it is related.

Fintasys avatar Aug 30 '25 10:08 Fintasys

Hey @Fintasys!

Not being able to reproduce in staging makes this tricky, but it does make me think if it's something regarding the ProGuard rules? Today the SDK uses reflection in several spots, so the ProGuard rules stay intentionally broad to avoid runtime issues for developers, but there might be something worth checking if you have a custom set of rules there?

Also, in the devices that have this issue in Production, are you able to test with them in Staging? The exact version (e.g Pixel 8, etc) to see if it can be something around a specific device configuration?

One thing that could help, if possible to log in Production too, is the isConfigured flag: https://pub.dev/documentation/purchases_flutter/latest/purchases_flutter/Purchases/isConfigured.html, in case the SDK is not being properly started.

GuilhermeMota93 avatar Sep 08 '25 09:09 GuilhermeMota93

Seems it happened to OnePlus 8 Pro user with Android 11. I don't have this device, so I can't test, but maybe you have.

Screenshot_20250908-150526.png

Also here is the error stack.

          Fatal Exception: i8.J: There is no singleton instance. Make sure you configure Purchases before trying to get the default instance. More info here: https://errors.rev.cat/configuring-sdk
       at com.revenuecat.purchases.Purchases$Companion.getSharedInstance(Purchases.kt:11)
       at com.revenuecat.purchases.ui.revenuecatui.data.PurchasesImpl.<init>(PurchasesType.kt:3)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.InternalCustomerCenterKt.getCustomerCenterViewModel(InternalCustomerCenter.kt:20)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.InternalCustomerCenterKt.InternalCustomerCenter(InternalCustomerCenter.kt:1)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterKt$CustomerCenter$1.invoke(CustomerCenter.kt:2)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterKt$CustomerCenter$1.invoke(CustomerCenter.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:31)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterKt.CustomerCenter(CustomerCenter.kt:181)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterActivity$onCreate$1$1.invoke(CustomerCenterActivity.kt:2)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterActivity$onCreate$1$1.invoke(CustomerCenterActivity.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:31)
       at androidx.compose.material3.TextKt.ProvideTextStyle(Text.kt:90)
       at androidx.compose.material3.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:2)
       at androidx.compose.material3.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:31)
       at androidx.compose.material3.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:290)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterActivity$onCreate$1.invoke(CustomerCenterActivity.kt:2)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterActivity$onCreate$1.invoke(CustomerCenterActivity.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:83)
       at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:2)
       at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:31)
       at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:311)
       at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:2)
       at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:31)
       at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:1)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:2)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:31)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:2)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:1)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:45)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:1)
       at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:18)
       at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:1)
       at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:14)
       at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:16)
       at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:25)
       at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:16)
       at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:1)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:1)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:2)
       at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:7)
       at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:8)
       at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:1)
       at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:1)
       at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:1)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:1)
       at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:2)
       at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:119)
       at android.view.View.dispatchAttachedToWindow(View.java:20483)
       at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3489)
       at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
       at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
       at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
       at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2435)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1948)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8177)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
       at android.view.Choreographer.doCallbacks(Choreographer.java:796)
       at android.view.Choreographer.doFrame(Choreographer.java:731)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:223)
       at android.app.ActivityThread.main(ActivityThread.java:7680)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:423)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
        

Fintasys avatar Sep 08 '25 13:09 Fintasys

Hello, I have the same problem. In the production version I see crashes in crashlytics. In testing, no one from our team has had this happen.

          Caused by kotlin.UninitializedPropertyAccessException: There is no singleton instance. Make sure you configure Purchases before trying to get the default instance. More info here: https://errors.rev.cat/configuring-sdk
       at com.revenuecat.purchases.Purchases$Companion.getSharedInstance(Purchases.kt:1014)
       at com.revenuecat.purchases.ui.revenuecatui.data.PurchasesImpl.<init>(PurchasesType.kt:61)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.InternalCustomerCenterKt.getCustomerCenterViewModel(InternalCustomerCenter.kt:504)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.InternalCustomerCenterKt.InternalCustomerCenter(InternalCustomerCenter.kt:77)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterKt$CustomerCenter$1.invoke(CustomerCenter.kt:31)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterKt$CustomerCenter$1.invoke(CustomerCenter.kt:30)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
       at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
       at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:390)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterKt.CustomerCenter(CustomerCenter.kt:30)
       at com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenterActivity$onCreate$1$1.invoke(CustomerCenterActivity.kt:32)

I initialize RevenueCat via Hilt Dependency injection like this

  @Provides
    @Singleton
    fun provideRevenueCat(app: Application): Purchases {
        if (BuildConfig.DEBUG) {
            Purchases.logLevel = LogLevel.DEBUG
        }
        
        return Purchases.configure(
            PurchasesConfiguration.Builder(
                context = app,
                apiKey = BuildConfig.REVENUECAT_API_KEY
            ).build()
        )
    }

In places where RC is needed, it is injected via Hilt. Nowhere in the project is Purchases.sharedInstance used. Paywall is not displayed before the user is logged into RC.

Version: 9.7.1

jvojacek avatar Sep 30 '25 14:09 jvojacek

Hey @jvojacek, thanks for reporting!

We recently shipped a possible fix on the Android SDK version 9.15.0 (released 25 Nov) - could you try updating to the latest available version and see how it works for you?

GuilhermeMota93 avatar Dec 04 '25 16:12 GuilhermeMota93

Hi all!

We've had reports that updating to the newer versions (that contain a fix related to the crash from 9.15.0 onwards) helps with this issue. I will go ahead and close this for now, but if anything else comes up, please feel free to reach out!

GuilhermeMota93 avatar Dec 18 '25 09:12 GuilhermeMota93