koin: java.util.NoSuchElementException when calling getOrNull() while creating an instance of an injected class with parameters
Describe the bug
Koin crashes with the following exception when resolving an instance with parameters that has a dependant call to getOrNull() (which gets not provided) to create the instance.
java.util.NoSuchElementException: ArrayDeque is empty.
at kotlin.collections.ArrayDeque.removeFirst(ArrayDeque.kt:145)
at org.koin.core.scope.Scope.resolveInstance(Scope.kt:213)
To Reproduce
- Create a definition that
(a) gets parameters from
parametersOf()(b) requires a call togetOrNull()to create the instance for this definition
factory { params ->
MyClass(
name = params.get(),
optionalInjectedParameter = getOrNull()
)
}
- Do not provide a definition for the parameter that should be resolved via
getOrNull() - Inject it somewhere
val myInjectedClass = get<MyClass> {
parametersOf("Some parameter")
}
Whats the problem
- Koin calls
Scope.resolveInstance()forMyClassand puts the parameters on the_parameterStack. It then callsScope.resolveValue()to create an instance ofMyClass. - While creating the instance Koin does a call to
getOrNull()as we defined it to provide the optional parameter if it is available. It callsScope.resolveValue()again for the optional parameter and ends up calling_parameterStack.clear()andthrowDefinitionNotFound()from there. The exception is caught within getOrNull() so it gracefully returnsnullfor the optional parameter from there and the instance ofMyClassgets created correctly inScope.resolveInstance(). - But afterwards it tries to remove the parameters of
MyClasswith_parameterStack.removeFirst(). And since the stack was already cleared from within thegetOrNull()call it crashes here.
Expected behavior
Koin should create the instance correctly and should not fail due to intentional optional parameters.
Please note that it can also be the case that we need to call getOrNull() from the init block of the injected class for some reasons and not only provide it as a constructor parameter.
Koin project used and used version (please complete the following information):
koin-core version 3.1.2
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 27
- Comments: 16 (7 by maintainers)
Commits related to this issue
- Workaround a bug in Koin This should hopefully fix java.util.NoSuchElementException as in InsertKoinIO/koin#1149 — committed to MM2-0/Kvaesitso by MM2-0 3 years ago
- Fix an issue where concurrent calls to koin.get would create a race condition resulting in this stack trace: Fatal Exception: java.util.NoSuchElementException ArrayDeque is empty. kotlin.collections.... — committed to npresseault/koin by npresseault 2 years ago
Ok, let see what’s going on 😕 we need to reproduce the problem.
Fixed in 3.1.4 - 43574dcae258627849a76e1832b8095ce35a4560
I have the same problem. After the release, many users reported this exception, but I can’t reproduce it myself
Hi all, also started seeing this issue the first time when we migrated from
3.0.2to3.1.2I’ve just run into this issue on Koin 3.1.5. I’m honestly at a loss as to how
removeFirstOrNullcan throw aNoSuchElementException. I’ve gotten about ~30 crashes in the last week since upgrading from 2.1.6Fatal Exception: java.util.NoSuchElementException ArrayDeque is empty. kotlin.collections.ArrayDeque.removeFirst (ArrayDeque.kt:145) kotlin.collections.ArrayDeque.removeFirstOrNull (ArrayDeque.java:157) org.koin.core.scope.Scope.resolveInstance (Scope.kt:244) org.koin.core.scope.Scope.get (Scope.kt:204) org.koin.core.scope.Scope.getOrNull (Scope.kt:172)
This bug is still present in latest releases with
removeFirstOrNull. This happens when we use koin to get the instance of an injected class across with parameters across multiple threads. In our case, the creation of this instance was done using Dispatchers.default which is backed by a thread pool.This is a race condition hence why it is hard to reproduce but I bet that it could be done in a small project doing multithreading.
Hi! Is there any update about this issue? I have the same problem 😞 I reproduced the same bug when using
getOrNull()and I also was able to reproduce this crash usingget()when dependency was created using multiple scopes (when some dependency is not found in the first scope but in some linked scope, parameters stack is also cleaned which causes crash later on)I was able to work around it but I’m afraid it has a potential to 🔥 later on unexpectedly since it’s a rather subtle bug
Koin project used and used version:
Koin core version 3.1.1