skip to content

What do compilerOptions { languageVersion } and apiVersion mean in the Kotlin Gradle Plugin, and when would you set them?

level: middleimportance: should knowfreq 45%

answer

  1. languageVersion = source syntax/feature level
  2. apiVersion = stdlib API you may call
  3. apiVersion <= languageVersion
  4. both default to the compiler version
  5. used for migration / library compat

basics

~20 s

languageVersion tells the Kotlin compiler which version of the Kotlin language/syntax to accept; apiVersion restricts which stdlib/runtime API you may use to that version. You set them to compile in a compatibility mode older than the compiler you're running.

solid answer

~40 s

Both are compiler options under `kotlin { compilerOptions { … } }`, set with the `KotlinVersion` enum. `languageVersion` controls the source language level — the syntax and language features the compiler accepts and the semantics it applies; e.g. running a 2.0 compiler but with `languageVersion = KOTLIN_1_9` to ease a gradual migration. `apiVersion` caps the Kotlin **library API** you are allowed to call, so you don't accidentally use stdlib declarations newer than your minimum supported Kotlin runtime; it must be ≤ `languageVersion`. Typical reasons: library authors who must stay compatible with consumers on older Kotlin, or teams migrating across a major compiler bump in controlled steps. If unset, both default to the compiler's own version. They are independent of `jvmTarget`, which is about emitted JVM bytecode, not Kotlin language level.

code

kotlin · 10 lines
kotlin
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion

kotlin {
    compilerOptions {
        // Run a newer compiler but keep older language semantics during migration
        languageVersion.set(KotlinVersion.KOTLIN_1_9)
        // Don't call stdlib APIs newer than what consumers ship
        apiVersion.set(KotlinVersion.KOTLIN_1_9)
    }
}

go deeper

for a junior

Recognize these exist and default to the compiler version; not expected to configure them.

for a middle

Distinguish languageVersion (syntax/features) from apiVersion (stdlib API) and give the migration use case.

for a senior

Explain library-compatibility motivations, the apiVersion ≤ languageVersion rule, and that both are independent of jvmTarget.

for a principal

Set org-wide policy: pin during major Kotlin migrations (e.g. K2) and define how library modules choose apiVersion for downstream consumers.

## Three independent version axes KGP exposes three things that all sound like "version" but mean different things: - **jvmTarget** — the JVM bytecode the compiler emits. - **languageVersion** — which Kotlin *language* the compiler reads (syntax + feature set + semantics). - **apiVersion** — which Kotlin *standard-library/runtime API* your code is permitted to reference. This question is about the latter two. ## languageVersion The Kotlin compiler can operate in a backward-compatibility mode: a newer compiler can be told to behave as if it were an older language version. You configure it as: ```kotlin import org.jetbrains.kotlin.gradle.dsl.KotlinVersion kotlin { compilerOptions { languageVersion.set(KotlinVersion.KOTLIN_1_9) } } ``` With this, code using features introduced after 1.9 will be rejected, and the compiler applies 1.9 semantics. The classic use case is a **gradual migration** across a major bump (e.g. the K2 / 2.0 change): you upgrade the compiler but pin `languageVersion` to the previous level so the codebase keeps building unchanged, then lift the pin later. ## apiVersion `apiVersion` restricts which declarations from the Kotlin stdlib and runtime you may call to those available in that version: ```kotlin kotlin { compilerOptions { apiVersion.set(KotlinVersion.KOTLIN_1_8) } } ``` If you call a stdlib function introduced in 1.9 while `apiVersion` is 1.8, the compiler errors. **Library authors** use this so a library compiled with a new toolchain still runs against the older Kotlin runtime their consumers ship. The constraint `apiVersion ≤ languageVersion` must hold. ## Defaults and relationships If you set neither, both equal the compiler's bundled version (so a Kotlin 2.0 compiler defaults both to 2.0). They have nothing to do with `jvmTarget`: you can target JVM_17 bytecode while using `languageVersion = 1.9`. Don't reach for these knobs casually — most application builds should track the compiler version and only pin during a deliberate migration or for library compatibility.

  • Why must apiVersion be less than or equal to languageVersion?
    You can't reference a library API from a Kotlin version newer than the language level you're compiling against — the compiler enforces apiVersion ≤ languageVersion to keep that coherent.
  • Do these affect emitted bytecode version?
    No. languageVersion/apiVersion are Kotlin-level concerns; jvmTarget is the independent knob for JVM bytecode. You can mix, e.g. languageVersion 1.9 with jvmTarget JVM_21.

saying these in an interview costs you the question

  • Confusing languageVersion with jvmTarget (Kotlin language level vs JVM bytecode).
  • Saying apiVersion can exceed languageVersion — the compiler rejects that.

context