Migrate Android projects from KAPT to KSP annotation processing. Triggers on: kapt, ksp, annotation processing, build speed, Hilt to KSP, Room to KSP, or build.gradle files containing kapt dependencies.
KAPT (Kotlin Annotation Processing Tool) works by generating Java stubs from Kotlin code, then running standard Java annotation processors against those stubs. This means:
KSP (Kotlin Symbol Processing) reads Kotlin source code directly through a Kotlin compiler plugin. This means:
KAPT is in maintenance mode. Google recommends migrating to KSP for all annotation processing. Major libraries (Hilt/Dagger, Room, Moshi, Glide) all support KSP.
Follow these 6 steps to migrate from KAPT to KSP:
Scan your project for:
kotlin("kapt") or id("org.jetbrains.kotlin.kapt") plugin declarationskapt(...) dependency declarationskaptTest(...) and kaptAndroidTest(...) test dependencieskapt { arguments { ... } } configuration blockskapt.incremental.apt or other kapt settings in gradle.propertiesList every library that uses KAPT and check if it supports KSP. See references/hilt.md and references/room.md for library-specific details.
Add the KSP Gradle plugin. The KSP version must align with your Kotlin version.
// Project-level build.gradle.kts
plugins {
id("com.google.devtools.ksp") version "<KOTLIN_VERSION>-<KSP_RELEASE>" apply false
}
KSP version format: <kotlin-version>-<ksp-release>. For example:
2.0.0-1.0.242.0.21-1.0.282.1.0-1.0.29Check KSP releases for the latest version matching your Kotlin version.
For each module, apply the KSP plugin and swap dependencies:
plugins {
id("com.google.devtools.ksp")
}
dependencies {
// Before:
// kapt("com.example:processor:1.0")
// After:
ksp("com.example:processor:1.0")
// Test dependencies too:
// kaptTest("com.example:processor:1.0")
kspTest("com.example:processor:1.0")
// Android test dependencies:
// kaptAndroidTest("com.example:processor:1.0")
kspAndroidTest("com.example:processor:1.0")
}
Migrate one library at a time. Build and test after each migration.
KAPT and KSP use different syntax for passing arguments to processors:
// KAPT syntax:
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas")
arg("room.incremental", "true")
}
}
// KSP syntax:
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
arg("room.incremental", "true")
}
Once all processors are migrated to KSP:
kotlin("kapt") plugin from every modulekapt { ... } configuration blocksgradle.propertieskotlin("kapt") if you still use Data Binding with kapt. Data Binding does not yet support KSP../gradlew clean assembleDebug./gradlew testDebugUnitTest./gradlew connectedDebugAndroidTest| Error | Cause | Fix |
|---|---|---|
Unresolved reference: ksp | KSP plugin not applied to the module | Add id("com.google.devtools.ksp") to the module's plugins block |
KSP version X does not match Kotlin version Y | KSP/Kotlin version mismatch | Use KSP version that matches your Kotlin version exactly |
Could not resolve com.example:processor | Library doesn't have a KSP artifact, or wrong artifact ID | Check library docs — some use a different artifact for KSP |
| Nullability errors in generated code | KSP sees actual Kotlin types (stricter than KAPT) | Fix source code nullability — see references/room.md |
DefaultImpls errors | Room < 2.6.0 with default interface methods | Update Room to 2.6.0+ — see references/room.md |
| Build succeeds but app crashes at runtime | Generated code differences between KAPT and KSP | Clean build, check for mixed KAPT/KSP in same module |