E08190: circular dependency detected in component injection chain
What went wrong
A circular dependency has been detected in the component injection chain. Component A requires Component B, which requires Component A (directly or transitively). Circular dependencies make object creation impossible.
Each tangle of components is reported once, at the member registered first, with one cycle through it. No order of registrations could satisfy a cycle, so its members are not also reported as used before registration (E08200). The failing source in the [EXAMPLE] section below (bad.ek9) has OrderService and BillingService each injecting the other.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 671 (How does EK9 prevent circular dependencies in DI?)
- ek9 -q 797 (How does EK9 detect circular component injection at compi...)
How to fix it
- Map out the dependency chain to find the cycle
- Extract shared logic into a new component
- Use an abstract trait to break the direct dependency
- Consider if the circular dependency indicates a design problem
- Then register the component that needs nothing first (good.ek9 below: BillingService no longer injects Orders, so it is registered before OrderService)
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08190: circular dependency detected in component injection chain
#!ek9 defines module error.e08190.bad defines component Orders as abstract place() as abstract Billing as abstract charge() as abstract OrderService is Orders billing as Billing! override place() billing.charge() default operator ? BillingService is Billing orders as Orders! override charge() orders.place() default operator ? defines application shopApp register OrderService() as Orders register BillingService() as Billing defines program Shop() with application of shopApp orders as Orders! orders.place()
Fixed: Break the cycle: Billing needs nothing from Orders, so it is registered first
#!ek9 defines module error.e08190.good defines component Orders as abstract place() as abstract Billing as abstract charge() as abstract OrderService is Orders billing as Billing! override place() billing.charge() default operator ? BillingService is Billing override charge() Stdout().println("charged") defines application shopApp register BillingService() as Billing register OrderService() as Orders defines program Shop() with application of shopApp orders as Orders! orders.place()
Questions and answers
These Q&A entries show E08190 and its fix: