skip to content

How do you enable Explicit API mode in a Kotlin Gradle build, and what is the difference between strict and warning levels?

level: middleimportance: must knowfreq 40%

answer

  1. explicitApi() = strict (errors), explicitApiWarning() = warning
  2. explicitApi = ExplicitApiMode.Strict/Warning/Disabled
  3. Sugar over -Xexplicit-api=...
  4. Start warning, migrate, then flip strict
  5. Scope to library/main, skip tests

basics

~10 s

In your Gradle build script's kotlin block, call explicitApi() for strict mode (build fails) or explicitApiWarning() for warnings only. Under the hood it passes a -Xexplicit-api compiler flag.

solid answer

~40 s

In the Kotlin Gradle DSL, the kotlin { } extension exposes explicitApi() and explicitApiWarning(). explicitApi() sets strict mode, which surfaces violations as compilation errors and fails the build; explicitApiWarning() reports the same issues as warnings without failing. Both are sugar over the compiler argument -Xexplicit-api=strict / -Xexplicit-api=warning, which you can also pass directly via freeCompilerArgs (or the older kotlinOptions). You can also set the explicitApiMode property to ExplicitApiMode.Strict, Warning, or Disabled. A common pattern is enabling it for published library modules but not for test or sample source sets, since tests don't need a curated public surface — Gradle applies it to the main compilation but you can scope it as needed.

code

kotlin · 12 lines
kotlin
kotlin {
    explicitApi() // strict
}

// equivalent low-level form:
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
kotlin { explicitApi = ExplicitApiMode.Strict }

// raw flag:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
    compilerOptions.freeCompilerArgs.add("-Xexplicit-api=strict")
}

go deeper

for a junior

Knows you add explicitApi() in the kotlin block.

for a middle

Distinguishes explicitApi() strict from explicitApiWarning(), and names the ExplicitApiMode enum / -Xexplicit-api flag.

for a senior

Describes a warning-to-strict migration and CI enforcement, and scoping to main vs test.

for a principal

Standardizes the policy across many library modules (convention plugin), balances strictness with build noise, and ties it into release governance.

## Enabling it via the Kotlin Gradle DSL The `kotlin { }` extension provides two convenience functions: ```kotlin // build.gradle.kts kotlin { explicitApi() // strict — violations are ERRORS, build fails // explicitApiWarning() // warnings only — build still succeeds } ``` These are shorthand for setting the **`explicitApiMode`** property: ```kotlin import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode kotlin { explicitApi = ExplicitApiMode.Strict // or .Warning or .Disabled } ``` ## The underlying compiler flag Both helpers ultimately add a compiler argument: - `-Xexplicit-api=strict` - `-Xexplicit-api=warning` - `-Xexplicit-api=disable` You can pass it manually if you prefer or need finer control: ```kotlin tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach { compilerOptions.freeCompilerArgs.add("-Xexplicit-api=strict") } ``` ## Strict vs warning | Mode | Reported as | Build outcome | |------|-------------|---------------| | **strict** (`explicitApi()`) | compile **errors** | **fails** on any violation | | **warning** (`explicitApiWarning()`) | compile **warnings** | succeeds | | **disable** | nothing | succeeds | The `-X` prefix means these are still technically experimental/advanced compiler flags, but the Gradle DSL functions are the stable, recommended entry point. ## Scoping The Kotlin Gradle plugin applies the mode to the module's compilations. **Test source sets do not need a curated public API**, so a typical approach is to enable it on library/main modules only — application and test modules usually leave it off. A migration strategy is to start with `explicitApiWarning()`, clean up the reports incrementally, then flip to `explicitApi()` and wire it into CI so regressions fail the build.

  • How would you migrate a large existing library to strict mode without breaking CI immediately?
    Turn on explicitApiWarning() first, fix the reported declarations gradually, then switch to explicitApi() and let CI enforce it.
  • Should you enable it on test source sets?
    Usually not — tests have no curated public surface, so the curation noise adds no value there.

saying these in an interview costs you the question

  • Saying explicitApi() only warns instead of failing the build
  • Not knowing it maps to -Xexplicit-api
  • Claiming there's no warning-only level
  • Thinking you must edit the compiler invocation manually — the DSL function exists
  • Confusing it with enabling a separate plugin

context