Fixing the "LocalNavController Not Provided" Crash in Jetpack Compose

intermediate๐Ÿ“ฑ Android2026-07-06| Android Studio, Jetpack Compose, Navigation Component (androidx.navigation:navigation-compose)

Error Message

java.lang.IllegalStateException: CompositionLocal LocalNavController not provided
#android#jetpack-compose#kotlin#navigation

The IncidentYour app builds perfectly. The Gradle sync is green. But the moment you tap a button to navigate, the app vanishes. You check Logcat to find a wall of red text: java.lang.IllegalStateException: CompositionLocal LocalNavController not provided.

This error is the Jetpack Compose version of a NullPointerException. It occurs when a Composable tries to pull a NavController from the environment, but finds nothing there. Essentially, you're asking for a tool that hasn't been put in the toolbox yet.

TL;DR: The 30-Second FixIf you use a custom LocalNavController, you must wrap your UI in a CompositionLocalProvider. This is usually done at the root of your MainActivity.

val navController = rememberNavController()

CompositionLocalProvider(LocalNavController provides navController) {
    // Your App Content
    MainScreen()
}

Why This HappensThink of CompositionLocal as a way to pass data down the UI tree behind the scenes. It saves you from "prop-drilling," which is the tedious process of passing a navController through ten different function parameters just to reach one button.

The crash triggers when LocalNavController.current is called, but the parent hierarchy lacks a provider. This typically stems from three specific scenarios:

  • The Missing Root: You defined the staticCompositionLocalOf but forgot to wrap your NavHost in the provider.- Isolated Previews: Android Studio Previews run in a vacuum. They don't know your MainActivity exists, so they can't see the controller you defined there.- Manual Definition Errors: You might have initialized the local with an error() block that triggers because no default value was supplied.## Step-by-Step Solutions### 1. The Global Root SetupMost developers run into this because the provider is missing at the top level. Open your MainActivity.kt and ensure the CompositionLocalProvider wraps your entire navigation graph. Using staticCompositionLocalOf is best here because the controller instance rarely changes during the app's lifecycle.
// 1. Define the local (usually in a NavGraph.kt file)
val LocalNavController = staticCompositionLocalOf<NavHostController> {
    error("No NavController found!")
}

// 2. Wrap your content
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState) {
            setContent {
                val navController = rememberNavController()
                CompositionLocalProvider(LocalNavController provides navController) {
                    AppNavigation() 
                }
            }
        }
    }
}

2. Fixing the "Render Problem" in PreviewsIf your app runs on a physical device but the Preview tab shows a grey box, you need a mock provider. Previews need their own local context. Since you aren't actually navigating between screens in a static preview, a simple rememberNavController() is enough to satisfy the compiler.

@Preview(showBackground = true)
@Composable
fun MyScreenPreview() {
    val mockController = rememberNavController()
    CompositionLocalProvider(LocalNavController provides mockController) {
        MyScreen()
    }
}

3. Scoping to the NavHostIf you prefer not to make the controller global, you can wrap only the NavHost. However, be careful. Any Composable that calls LocalNavController.current outside of this specific block will still crash the app instantly.

Verification ChecklistDon't assume it's fixed just because the first screen loads. Run these three checks:

  • The Cold Start: Kill the app process and restart. Ensure the initial startDestination loads without a hitch.- The 3-Level Test: Navigate at least three screens deep into your UI. If LocalNavController.current works at the deepest level, your hierarchy is correctly configured.- Preview Rendering: Check the Design view in Android Studio. If the "Render Problem" overlay is gone, your mock provider is working.## Pro Tip: Performance MattersWhen using CompositionLocal, prefer staticCompositionLocalOf for the NavController. Unlike a standard compositionLocalOf, the static version doesn't track every single consumer. Since your NavController instance is usually created once and never swapped, the static version saves the overhead of unnecessary recompositions across your entire app.

Related Error Notes