Skip to main content
Version: 4.2

Troubleshooting

This page lists the errors Koin reports, what causes them and how to fix them. It also covers the tools to find a problem before it reaches users, and the patterns that lead to these errors. The messages are quoted as Koin prints them, so you can search the page for the text of your stack trace.

Find problems early​

Koin gives you three ways to see a configuration error, from the earliest to the latest.

  • Compile time: with the Koin Compiler Plugin, a missing dependency or a dependency cycle fails the build. The error names the definition, the parameter and the module. See Compile-Time Safety for every check and error code.
  • In the IDE: the Koin IDE plugin shows where each definition is declared, where it is used and what is missing, while you write code.
  • In tests: without the Compiler Plugin, call verify() on your modules in a JVM unit test. It checks that each constructor parameter has a definition. See Verify your configuration.
class ModuleCheckTest {

@Test
fun checkKoinModules() {
appModule.verify()
}
}

Logging​

Koin logs nothing by default (EmptyLogger). Turn logging on to see each definition load and each instance resolution:

startKoin {
printLogger(Level.DEBUG)
modules(appModule)
}
LevelWhat you see
Level.DEBUGEvery resolution, with the scopes Koin searched. Use it to understand a failure
Level.INFOStartup summary, such as Started 42 definitions in 1.2 ms. The default for printLogger()
Level.WARNINGWarnings, such as a definition that overrides another
Level.ERRORErrors only
Level.NONENothing

On Android, use androidLogger(Level.DEBUG) to write to Logcat. See Starting Koin for the logger options.

Level.DEBUG slows down resolution. Keep it for debugging sessions, not for release builds.

Runtime errors​

No definition found​

NoDefinitionFoundException: No definition found for type 'com.example.UserRepository' on scope '['_root_']'.
Check or add definition for type 'com.example.UserRepository' in scope '_root_'.

Koin was asked for a type that no loaded module declares. Check, in this order:

  • Module not loaded: the definition exists but its module is not in modules(...) or in an includes(...).
  • Missing qualifier: the definition has a qualifier and the request has none, or the reverse. The message then contains and qualifier '...'. See Qualifiers.
  • Interface not bound: the definition declares UserRepositoryImpl and the request asks for UserRepository. Bind the interface, see Definitions.
  • Wrong scope: the definition is scoped in a scope, and the request comes from another scope or from the root. The message lists the searched scopes. See Scopes.

For SavedStateHandle, the message says instead that it is provided by the ViewModel CreationExtras. Resolve the ViewModel with koinViewModel() or by viewModel() and take SavedStateHandle as a constructor parameter. See ViewModel.

Could not create instance​

InstanceCreationException: Could not create instance for '[Singleton: 'com.example.UserRepository']'

Koin found the definition, but creating the instance threw an exception. The real cause is the nested exception (Caused by:) in the stack trace. Often it is a NoDefinitionFoundException for one of the constructor parameters, or an exception thrown by the constructor itself.

Already existing definition​

DefinitionOverrideException: Already existing definition for [Singleton: 'com.example.ApiService'] at com.example.ApiService::_root_

Two modules declare the same type and qualifier, and overriding is off (allowOverride(false)). Remove the duplicate, give it a qualifier, or mark the intended one with .override(). See Definitions.

Scope errors​

MessageExceptionCause
Scope 'user_session' is closedClosedScopeExceptionThe scope was closed and something still asks it for an instance. Often a callback or a coroutine that outlives the screen
No scope found for id 'user_session'ScopeNotCreatedExceptiongetScope(id) was called before createScope(id, ...). Use getOrCreateScope or create the scope first
Scope with id 'user_session' is already createdScopeAlreadyCreatedExceptioncreateScope was called twice with the same id
No value for scope 'user_session' in [Scoped: ...]MissingScopeValueExceptionA scoped value declared with declare() was not provided for this scope
Activity should implement AndroidScopeComponentIllegalStateExceptionAn Android scope API was used in an Activity that has no scope. See Android Scopes

See Scopes for the scope lifecycle.

Injected parameters​

MessageExceptionCause
Can't get injected parameter #0 from DefinitionParameters[] for type 'kotlin.String'NoParameterFoundExceptionThe definition reads a parameter that the caller did not pass with parametersOf(...)
No value found for type 'kotlin.String'DefinitionParameterExceptionparams.get<T>() found no parameter of that type

See Injected Parameters.

Start and properties​

MessageExceptionCause
KoinApplication has not been startedIllegalStateExceptionCode used the global context (KoinComponent, by inject()) before startKoin. On Android, check that your Application class is declared in the manifest
A Koin Application has already been startedKoinApplicationAlreadyStartedExceptionstartKoin was called twice. In tests, call stopKoin() after each test
Can't resolve Context instance. Please use androidContext() function in your KoinApplication configuration.MissingAndroidContextExceptionA definition uses androidContext() and startKoin has no androidContext(this)
Property 'api_url' not foundMissingPropertyExceptiongetProperty("api_url") with no such property and no default value
No properties found for file '/koin.properties'NoPropertyFileFoundExceptionfileProperties() could not find the file

Compiler Plugin not applied​

NotImplementedError: Error while using 'single<T>()'. The Koin Compiler plugin is missing. Please fix your setup to use 'io.insert-koin.compiler.plugin' Koin Gradle Plugin.

The code uses the Compiler Plugin DSL (single<T>(), factory<T>(), startKoin<T>()) but the plugin is not applied to this Gradle module. See Compiler Plugin Setup.

Circular dependencies​

A cycle happens when two classes need each other in their constructors:

class SessionManager(private val authService: AuthService)
class AuthService(private val sessionManager: SessionManager)

With the Compiler Plugin, the build fails:

[Koin][KOIN-D004] Circular dependency detected:
com.example.AuthService → com.example.SessionManager → com.example.AuthService
Break with Lazy<T> injection or refactor to remove the cycle.

With verify(), the test fails with Circular injection between ... Fix your Koin configuration!.

Without those checks, Koin does not detect the cycle. Each class resolves the other until the call stack overflows, and the app crashes with a StackOverflowError.

Break the cycle with Lazy​

Make one side lazy, so it is resolved on first use and not during construction:

class AuthService(private val sessionManager: Lazy<SessionManager>)

val authModule = module {
single<SessionManager>()
single<AuthService>()
}

AuthService must not read sessionManager.value in its constructor or init block, or the cycle comes back.

Remove the cycle​

A lazy parameter hides the problem but keeps the coupling. Most cycles mean that both classes share a responsibility. Move it to a third class that both depend on, or make one side depend on an interface that exposes only what it needs.

class TokenStore

class SessionManager(private val tokenStore: TokenStore)
class AuthService(private val tokenStore: TokenStore)

Patterns that cause errors​

Resolving inside methods: calling get() or KoinComponent inside a class body hides its dependencies. The Compiler Plugin cannot check them, and a missing definition fails only when the method runs. Prefer constructor parameters. See KoinComponent for the cases where you need it.

// Hidden dependency, resolved late
class UserViewModel : ViewModel(), KoinComponent {
fun loadUser() {
val repository = get<UserRepository>()
}
}

// Visible dependency, checked at build time
class UserViewModel(private val repository: UserRepository) : ViewModel()

Creating dependencies yourself: private val api = ApiService() inside a class bypasses Koin. The class can't be tested with a fake, and its dependencies are not checked.

Qualifiers for different types: a qualifier is only needed when several definitions provide the same type. UserRepository and OrderRepository are already different types.

Work inside definitions: a definition should create an object, not run logic. Side effects in a single { } lambda run at an unpredictable time (first use), and on the main thread for createdAtStart. Keep the work in the class, or move startup work to Lazy Modules.

One module for the whole app: a single large module is hard to override in tests and to load lazily. Split by feature or layer. See Modules.

Scoped instances kept after close: a reference to a scoped instance stored in a single or a static field keeps it alive after its scope closes, and later calls may hit ClosedScopeException. Inject scoped instances only into objects of the same scope or shorter.

tip

Some problems only show up on real devices: slow resolutions on startup, scopes that never close, crashes in rare paths. To see them in real user sessions, see Production Monitoring.