question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unexpected DependencyLoopException

See original GitHub issue

Kodein 5.2.0 (5.0.0 failed too)

Following code for some reason throws a DependencyLoopException:

image

val kodein = Kodein.lazy {
 bind<Kodein>() with singleton { kodein }
 bind<Client>() with singleton { Client(instance()) }
 bind<A>() with singleton { A(instance()) }
}

class Client(override val kodein: Kodein) : KodeinAware {
 fun doSomething() { ... }
}

class A(override val kodein: Kodein) : KodeinAware {
 val client by instance<Client>()
 fun doSomething() {
  client.doSomething()
 }
}

fun main(args: Array<String>) {
 // Works
 val client by kodein.instance<Client>()
 client.doSomething()

 // Throws an exception
 val a by kodein.instance<A>()
 a.doSomething()
}

Replacing the Client binding with singleton { Client(kodein) } works. I feel like I’m missing something here, but it just doesn’t look right to me.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
SalomonBryscommented, Jul 2, 2018

I’ll investigate 😉

0reactions
SalomonBryscommented, Jul 2, 2018

Ooooh, this is suuuuuch a weird thing.

So, to understand why this is showing this exception, you need to understand how Kodein detects dependency loops.

You see, in a binding, the kodein variable is NOT the Kodein instance you constructed and used for retrieval. It is a Kodein that knows its parent nodes. Let me show you an example. Consider the following:

class A(b: B)
class B(c: C)
class C(a: A)

val kodein = Kodein {
    bind<A>() with singleton { A(instance()) }
    bind<B>() with singleton { B(instance()) }
    bind<C>() with singleton { C(instance()) }
}

When asking for first A, the singleton provided lambda is called with a this Kodein that knows “All my requests are going to be A dependencies”. The lambda asks for a B, so it creates a new Kodein instance that knows “I come from A, and all my requests are going to be B dependencies”. By the same logic, a new Kodein instance is later constructed that knows “I come from B before A, and all my requests are going to be C dependencies”. Then, when a A instance is requested from this last Kodein instance, it knows that there is a dependency loop that had arisen from asking an instance of a type that it is a dependency.

Now, remember that singleton bindings are initialized on first access. This means that the Kodein instance that is cached is the one that is created by the first need, which in your code is the line val client by kodein.instance<Client>(). So, what is cached is an intermediate instance whose internal state is “I come from Client, and all my requests are going to be Kodein dependencies”. Then, later you reuse that Kodein instance, giving it to your A constructor, which uses it to request a Client dependency. The loop is made, this Kodein instance thinks it already comes from the Client constructor. So it does what it’s supposed to: it throws an error.

I have no idea of how to prevent this other than saying DO NOT FREAKING DO THIS!: everything is working as it should!

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to fix nasty circular dependency issues once and for all in ...
Once we move each class to it's own file, it turns out that the very same application suddenly, utterly dies, seemingly beyond repair...
Read more >
Unexpected connection state when multiple requests at the ...
This is something I completly understand : the code is trying to access to the database with the same connection in parallel, but...
Read more >
ansible-galaxy collection install timeout · Issue #2302 - GitHub
We've seen ERROR! Unexpected Exception, this is probably a bug: ('The read operation timed out',) (10 minute time out) quite a few times....
Read more >
Handling Resolution Errors - Prism Library
Some common errors developers run into is a Service that was not registered or invalid XAML that generates an Exception when the View...
Read more >
Indexing is stuck forever for a project
After some moment my indexing is stuck forever. In the log of Webstorm I can see this error over and over again (every...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found