How to Fix 'Inconsistent JVM Target Compatibility' in Flutter with Kotlin 2.x and Gradle 8.x
How to Fix 'Inconsistent JVM Target Compatibility' in Flutter with Kotlin 2.x and Gradle 8.x
Introduction
If you recently upgraded your Flutter project to use a newer version of Kotlin or Gradle, you may have encountered this frustrating error when running flutter build apk:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':fluttercontactpicker:compileReleaseKotlin'.
> Inconsistent JVM Target Compatibility Between Java and Kotlin Tasks
Inconsistent JVM-target compatibility detected for tasks
'compileReleaseJavaWithJavac' (1.8) and 'compileReleaseKotlin' (21).
The plugin name may differ in your case — it could be any third-party Flutter plugin. But the core error is always the same: Java and Kotlin are compiling to different JVM versions. In this post, I'll explain what this error means, why it happens, and exactly how to fix it.
What Does This Error Actually Mean?
When Android builds your app, it compiles two types of source files:
- Java files → compiled by
javac(Java compiler) - Kotlin files → compiled by
kotlinc(Kotlin compiler)
Both compilers need to produce bytecode compatible with the same JVM version. Think of it like two people writing a document — one using Word 2003 format and another using Word 2023 format. They can't be merged cleanly.
In the error above:
compileReleaseJavaWithJavacwas targeting JVM 1.8compileReleaseKotlinwas targeting JVM 21
These are incompatible, so the Android Gradle Plugin (AGP) throws an error and refuses to build.
Why Does This Happen?
There are three common reasons this error appears:
1. You Upgraded Kotlin or Gradle
Newer versions of the Kotlin Gradle Plugin changed the default JVM target. Older versions defaulted to JVM 1.8. Newer versions (2.x+) default to JVM 21. If your third-party plugins still have JVM 1.8 hardcoded for Java but Kotlin picks up the new default, they conflict.
2. A Third-Party Plugin Has Outdated Config
Many Flutter plugins on pub.dev haven't been updated to align their Java and Kotlin JVM targets. Their build.gradle may hardcode:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
But their Kotlin compiler picks up a newer target from the global Kotlin settings — causing a mismatch.
3. The kotlinOptions DSL Is Deprecated
In Kotlin Gradle Plugin 2.x, the old way of setting the JVM target:
kotlinOptions {
jvmTarget = "17"
}
is now deprecated and treated as an error. You must use the new compilerOptions DSL, which many tutorials and Stack Overflow answers still show the old way.
The Environment Where This Occurred
- Flutter SDK: 3.x
- Kotlin Gradle Plugin: 2.2.20
- Gradle: 8.14
- AGP (Android Gradle Plugin): 8.x
- OS: Windows
How to Fix It
The cleanest fix is to force a consistent JVM target for all subprojects (including third-party plugins) from the root build.gradle.kts file.
Step 1 — Open build.gradle.kts
This is the root-level Gradle file, not the app-level one (android/build.gradle.kts).
Step 2 — Add This Block
Add the following after your existing subprojects blocks:
// Force consistent JVM target for all subprojects
subprojects {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
}
}
}
And to fix the Android library Java compile options for all plugins, add:
allprojects {
pluginManager.withPlugin("com.android.library") {
extensions.configure<com.android.build.gradle.LibraryExtension> {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
}
}
Step 3 — Also Fix Your App-Level build.gradle.kts
Make sure your own app is also consistently set to JVM 17 (android/app/build.gradle.kts):
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
}
Full Updated build.gradle.kts
Here's what your root-level build.gradle.kts should look like:
buildscript {
repositories {
google()
mavenCentral()
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
// Force consistent JVM target for all subprojects
subprojects {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
}
}
}
allprojects {
pluginManager.withPlugin("com.android.library") {
extensions.configure<com.android.build.gradle.LibraryExtension> {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
}
}
Common Mistakes to Avoid
❌ Using kotlinOptions (Deprecated in Kotlin 2.x)
// DO NOT USE — this is an error in Kotlin 2.x
kotlinOptions {
jvmTarget = "17"
}
✅ Use compilerOptions Instead
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
}
❌ Using afterEvaluate with evaluationDependsOn
// This will throw: "Cannot run afterEvaluate when project is already evaluated"
subprojects {
afterEvaluate { ... }
}
subprojects {
project.evaluationDependsOn(":app")
}
Use lazy task configuration (configureEach) instead — it avoids evaluation order issues entirely.
Why JVM 17 and Not 21?
JVM 17 is the current LTS (Long-Term Support) version recommended by both Google and JetBrains for Android development. It's stable, well-supported, and compatible with AGP 8.x. JVM 21 is newer but not yet the standard recommendation for Android projects as of 2026.
Verification Steps
After making these changes:
-
Clean the build:
flutter clean cd android ./gradlew clean cd .. -
Rebuild the app:
flutter build apk -
Verify success: You should see
BUILD SUCCESSFULwithout any JVM compatibility errors.
Key Takeaways
- This error is caused by Java and Kotlin compilers targeting different JVM versions
- It commonly appears after upgrading Kotlin to 2.x or Gradle to 8.x
- The fix goes in the root
build.gradle.kts, not the app-level one - Always use
compilerOptionsDSL —kotlinOptionsis deprecated and will fail - Avoid
afterEvaluatewhenevaluationDependsOnis present — useconfigureEachinstead - Set JVM 17 consistently everywhere: root Gradle, app Gradle, and all subprojects
References
- Kotlin JVM Toolchain documentation
- Android Gradle Plugin release notes
- Kotlin compilerOptions DSL migration guide
Fixed this issue while building Emergency 108 app. Hope this saves you hours of debugging!