What happens with missing or duplicate component registrations?

← DI Validation · Ref: Q798

EK9 validates application registrations at compile time for two common errors.

MISSING REGISTRATION (E08210)

When a program injects a component type that has no matching registration in the linked application, the compiler raises E08210. Every injection point must have a 'register' declaration.

DUPLICATE REGISTRATION (E08230)

When an application registers two concrete implementations for the same abstract type, the compiler raises E08230. Each abstract type must have exactly ONE registration per application.

CORRECT PATTERN

- Register exactly one concrete implementation per abstract type
- Use separate applications for different configurations
- Ensure all transitive dependencies are registered

See Q673 for missing registration details. See Q674 for duplicate registration details. See Q671 for circular dependencies.

Example

defines module qa.divalidation.missingduplicate

  defines component

    CacheLayer as abstract

      lookup() as abstract
        -> cacheKey as String
        <- cached as String?

      default operator ?

    ConcreteCache extends CacheLayer

      override lookup()
        -> cacheKey as String
        <- cached as String: "cached-" + cacheKey

      default operator ?

    Repository as abstract

      fetch() as abstract
        -> recordId as String
        <- fetched as String?

      default operator ?

    ConcreteRepo extends Repository

      override fetch()
        -> recordId as String
        <- fetched as String: "record-" + recordId

      default operator ?

  defines application

    CompleteConfig
      register ConcreteCache() as CacheLayer
      register ConcreteRepo() as Repository

  defines program

    RegistrationDemo() with application of CompleteConfig
      stdout <- Stdout()

      cacheService as CacheLayer!
      repoService as Repository!

      cachedItem <- cacheService.lookup("item-1")
      stdout.println(`Cache: ${cachedItem}`)

      record <- repoService.fetch("rec-1")
      stdout.println(`Repo: ${record}`)

Common mistakes

E08210 — The program injects both CacheLayer and Repository, but only CacheLayer is registered. Every injection point must have a matching registration. Add 'register ConcreteRepo() as Repository' to the application. See ek9 -h E08210 for details.

Incorrect:

      register ConcreteCache() as CacheLayer

Correct:

      register ConcreteCache() as CacheLayer
      register ConcreteRepo() as Repository
Other ways to ask this
  • What triggers E08210 missing registration?
  • What triggers E08230 duplicate registration?
  • How does EK9 validate application registrations at compile time?

Coming from another language?

Java: Spring throws NoSuchBeanDefinitionException (missing) or NoUniqueBeanDefinitionException (duplicate) at runtime. Python: runtime errors. Go: Wire detects at generation time. Rust: no standard DI. Kotlin: Koin throws at runtime. EK9: compile-time E08210/E08230 prevents both errors before deployment.

Keywords: application, duplicate, inject, registration, missing, DI, E08210, component, E08230