Mr.AndroidShin / Dev Tools

Debugging log · Gradle

"Inconsistent JVM-target compatibility" — when Java and Kotlin disagree

After updating my toolchain, a project that had built fine for months suddenly refused to compile with a message about JVM-target compatibility between compileJava and compileKotlin. Nothing in my code had changed. If you just bumped Android Gradle Plugin, the JDK, or Kotlin and got hit with this, here's what's going on and how to make it stop for good.

The short version: the Java compiler and the Kotlin compiler are targeting different JVM bytecode versions. Pin them both to the same target — ideally with a single Java toolchain — and the error disappears.

The error

Inconsistent JVM-target compatibility detected for tasks
'compileDebugJavaWithJavac' (17) and 'compileDebugKotlin' (11).

The two numbers are JVM bytecode targets. Here Java is compiling to 17 and Kotlin to 11. Gradle now treats that mismatch as an error rather than a warning, because linking bytecode built for two different JVM versions is a recipe for subtle runtime breakage. So instead of guessing, it stops.

Why they drifted apart

They usually start aligned and then one side moves. Common triggers:

The fix is simply to make both compilers agree on one number.

Fix A — the explicit way (both blocks)

Set the Java compatibility and the Kotlin target to the same value in your module's build.gradle:

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
    kotlinOptions {           // older Kotlin plugin
        jvmTarget = "17"
    }
}

On newer Kotlin plugins kotlinOptions is replaced by a compilerOptions block:

kotlin {
    compilerOptions {
        jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
    }
}

The exact DSL depends on your Kotlin version, but the principle is unchanged: the Java number and the Kotlin number must match.

Fix B — the clean way (one toolchain)

Better than keeping two numbers in sync is to declare a single Java toolchain and let both compilers inherit it. Then there's only one place to change, and they can't drift again:

kotlin {
    jvmToolchain(17)
}

This tells Gradle to compile both Java and Kotlin against JDK 17, downloading it if needed, regardless of which JDK you happen to be running Gradle with. I switched to this and stopped seeing the error entirely — there's simply no second number left to fall out of step.

Rule of thumb: one JVM target, declared once. A toolchain is the single source of truth; two hand-maintained numbers will eventually disagree.

How to confirm it's fixed

Version numbers here are illustrative; use whatever target your project actually needs, and keep both compilers on it.