E08170: an injected component is never assigned, not even with ':=?' - for a fallback, assign to a new variable ('chosen <- supplied' then 'chosen :=? injected')
What went wrong
You're assigning to an INJECTED component variable ('name as T!'). An injected variable is never assigned - not with ':=', and not with ':=?' either. The application sets it, and the compiler proves every injection a program reaches is registered (E08210, E08220), so it is always set: ':=?' would never apply.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 669 (Why can't I reassign an injected component variable?)
Rationale
Injection dependencies should remain stable after initialization. The application wiring manages the component lifecycle — manual reassignment would break the contract between application wiring and injection sites.
How to fix it
- Remove the assignment and use the injected component as it is.
- If you need a fallback, assign to a NEW variable and fall back to the injected one (the [EXAMPLE] section below: 'chosen' takes the supplied Timekeeper, then the injected one only if it is unset)
- If the component should be replaceable, do not inject it: pass it as a parameter or hold it in an ordinary variable or property.
Common causes
- Trying to change an injected dependency at runtime
- Using ':=?' on the injected variable as an "optional injection" fallback - it is never unset
- Habit from Spring/Guice, where an injected field can be reassigned or left null
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08170: an injected component is never assigned, not even with ':=?' - for a fallback, assign to a new variable ('chosen <- supplied' then 'chosen :=? injected')
#!ek9 defines module error.e08170.bad defines function report() <- rtn as String? timekeeper as Timekeeper! timekeeper :=? NoonKeeper() rtn: timekeeper.now() defines component Timekeeper as abstract now() as pure abstract <- rtn as String? NoonKeeper is Timekeeper override now() as pure <- rtn as String: "noon"
Fixed: For a fallback, assign to a new variable
#!ek9 defines module error.e08170.good defines function report() -> supplied as Timekeeper <- rtn as String? timekeeper as Timekeeper! chosen <- supplied chosen :=? timekeeper rtn: chosen.now() defines component Timekeeper as abstract now() as pure abstract <- rtn as String?
Questions and answers
These Q&A entries show E08170 and its fix: