koin: Crash in Koin 3.1.3: "SavedStateProvider with the given key is already registered"

Describe the bug When upgrading from Koin 3.1.2 to 3.1.3 we started getting some crashes in our app. We do not know for sure if Koin is at fault, but the stack trace implies it:

Fatal Exception: java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
       at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.java:111)
       at androidx.lifecycle.SavedStateHandleController.attachToLifecycle(SavedStateHandleController.java:50)
       at androidx.lifecycle.SavedStateHandleController.create(SavedStateHandleController.java:70)
       at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:67)
       at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:169)
       at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:139)
       at org.koin.androidx.viewmodel.ViewModelResolverKt.resolveInstance(ViewModelResolverKt.java:15)
       at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExtKt.java:65)
       at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExtKt.java:52)
       at org.koin.androidx.viewmodel.ext.android.ComponentCallbackExtKt.getViewModel(ComponentCallbackExtKt.java:61)
       at org.koin.androidx.viewmodel.ext.android.ComponentCallbackExtKt.getViewModel$default(ComponentCallbackExtKt.java:54)
       at org.koin.androidx.viewmodel.ext.android.ComponentCallbackExtKt.getViewModel$default(ComponentCallbackExtKt.java:50)
       at com.action.consumerapp.feature.search.ProductSearchFragment$special$$inlined$viewModel$default$1.invoke(ProductSearchFragment.java:63)
       at com.action.consumerapp.feature.search.ProductSearchFragment$special$$inlined$viewModel$default$1.invoke(ProductSearchFragment.java:41)
       at kotlin.UnsafeLazyImpl.getValue(UnsafeLazyImpl.java:81)
       at com.action.consumerapp.feature.search.ProductSearchFragment.getViewModel(ProductSearchFragment.java:52)
       at com.action.consumerapp.feature.search.ProductSearchFragment.onDestroy(ProductSearchFragment.java:100)
       at androidx.fragment.app.Fragment.performDestroy(Fragment.java:3217)
       at androidx.fragment.app.FragmentStateManager.destroy(FragmentStateManager.java:756)
       at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:333)
       at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1788)
       at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1721)
       at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1658)
       at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488)
       at android.os.Handler.handleCallback(Handler.java:883)
       at android.os.Handler.dispatchMessage(Handler.java:100)
       at android.os.Looper.loop(Looper.java:241)
       at android.app.ActivityThread.main(ActivityThread.java:7604)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)

To Reproduce Unfortunately, we have not been able to reproduce the issue ourselves.

Expected behavior The app should not crash.

Koin project used and used version (please complete the following information): io.insert-koin:koin-android:3.1.3

Additional moduleDefinition We use viewModel { in our module and by viewModel() in our fragments/activities. Could this change from the changelog be related? “[DEPRECATED] [android] - by stateViewModel() is deprecated. state parameter is not needed anymore. It’s now merged into viewModel(), to inject SavedStateHandle”

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 8
  • Comments: 37 (14 by maintainers)

Commits related to this issue

Most upvoted comments

Hey I’m getting this more and more frequently - What’s going on here? Is there a work around for now?

I am not using a sharedviewmodel just a normal viewmodel and it seems to happen randomly. Please help since this is big issue

Fixed 🎉 - The Google’s ViewModel API pushed to resolve factory regarding the main thread, provoking the “SavedStateProvider with the given key is already registered” error.

It should be ok for 3.1.6

anyone has a sample app to help reproduce directly the case?

hi, @arnaudgiuliani I have created a project to help you reproduce this issue. https://github.com/corgivn/koin-example-issue-shared-viewmodel Pls help to take a look Many thanks

Wow. It is still not fixed. For my own apps I use Koin. At office work I use Hilt. And now I think to use Hilt everywhere. Quite disappointed

It is reproduced in 3.1.5 version. Are you going to fix it somehow?

private val viewModel by sharedViewModel<BaseWalletViewModel>() { parametersOf(requireActivity()) }

viewModel<BaseWalletViewModel> { (activity: Activity) -> WalletViewModel(get(), get(),...) }

java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
        at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.java:111)
        at androidx.lifecycle.SavedStateHandleController.attachToLifecycle(SavedStateHandleController.java:50)
        at androidx.lifecycle.SavedStateHandleController.create(SavedStateHandleController.java:70)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:67)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at org.koin.androidx.viewmodel.ViewModelResolverKt.resolveInstance(ViewModelResolver.kt:15)
        at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExt.kt:67)
        at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExt.kt:53)
        at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel$default(ScopeExt.kt:45)
        at org.koin.androidx.viewmodel.ext.android.FragmentExtKt.getSharedViewModel(FragmentExt.kt:59)
        at com.b9.app.features.screens.wallet.WalletScreen$special$$inlined$sharedViewModel$default$2.invoke(FragmentExt.kt:61)
        at com.b9.app.features.screens.wallet.WalletScreen$special$$inlined$sharedViewModel$default$2.invoke(FragmentExt.kt:39)
        at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
        at com.b9.app.features.screens.wallet.WalletScreen.getViewModel(WalletScreen.kt:46)
        at com.b9.app.features.screens.wallet.WalletScreen.onViewCreated(WalletScreen.kt:57)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2967)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:529)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:259)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1785)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1709)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1646)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:480)
        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:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

I have the same issue (working within an NDA so I can’t share my code but here are the steps to reproduce):

// module
    viewModel {
        ScreenSettingsVM(
            app = androidApplication()
        )
    }
@Composable
fun ScreenSettings(modifier: Modifier = Modifier, navController: NavHostController) {
    val vm = getViewModel<ScreenSettingsVM>()
    .
    .
}

Steps are:

  • Go to settings screen above
  • Open an external email app via an intent
  • Navigate back to app via system back
  • Leave settings screen
  • Re-enter settings screen
  • Crash
    // Koin main features for Android (Scope,ViewModel ...)
   implementation "io.insert-koin:koin-android:3.1.5"
   // Koin Java Compatibility
   implementation "io.insert-koin:koin-android-compat:3.1.5"

Please note that it does not happen 100% of the time - I would say 30% of the time it will happen

Koin 3.2 reintroduces the default factory which avoids using AbstractSavedStateViewModelFactory. This will solve some of the problems hopefully.

yes, fixes in 3.1.6 will be merged in 3.2.0

working on it

I’m currently using version 3.1.6 and still get this crashes when using shared view model on screen orientation change

I updated to ‘3.2.0-beta-1’ but still crashing 😦

After staying safe on 3.1.2 for a while, we upgraded to 3.1.6 when seeing this issue was fixed. But our crash reporting tool shows that it started happening again to multiple users.

I have not been able to reproduce it myself yet.

Fatal Exception: java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
       at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.java:111)
       at androidx.lifecycle.SavedStateHandleController.attachToLifecycle(SavedStateHandleController.java:50)
       at androidx.lifecycle.SavedStateHandleController.attachHandleIfNeeded(SavedStateHandleController.java:101)
       at androidx.lifecycle.AbstractSavedStateViewModelFactory.onRequery(AbstractSavedStateViewModelFactory.java:103)
       at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:160)
       at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:139)
       at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:44)
       at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:31)
       at com.action.consumerapp.feature.search.ProductSearchFragment.getViewModel(ProductSearchFragment.kt:53)
       at com.action.consumerapp.feature.search.ProductSearchFragment.onDestroy(ProductSearchFragment.kt:101)
       at androidx.fragment.app.Fragment.performDestroy(Fragment.java:3251)
       at androidx.fragment.app.FragmentStateManager.destroy(FragmentStateManager.java:780)
       at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:335)
       at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840)
       at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1764)
       at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701)
       at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8663)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)