Введение: почему KaptExecution ломает сборку и как это исправить
Если вы хоть раз сталкивались с ошибкой A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution, то знаете, как это выбивает из колеи. Сборка падает, Gradle выдает красный текст, а в логах — непонятные stacktraces. На Stack Overflow этот вопрос собрал тысячи просмотров, но большинство ответов — просто "попробуй очистить кеш". Мы пойдем дальше.
В этой статье мы не просто дадим готовые решения. Мы заглянем под капот механизма Kapt (Kotlin Annotation Processing Tool) и разберем, что именно происходит, когда Gradle запускает KaptExecution. Вы узнаете, как работает генерация кода, где прячутся типичные ошибки и как их предотвратить. А главное — получите работающие примеры на Kotlin, которые можно сразу применить в своем проекте.
Это образовательный материал для pythonlib.ru, адаптированный для разработчиков, которые хотят не просто копировать команды, а понимать, что происходит внутри сборщика.
Что такое KaptExecution и зачем он нужен
Kapt — это плагин для Kotlin, который позволяет использовать Java-совместимые annotation processors (например, Dagger, Room, Glide, Moshi) в Kotlin-проектах. Когда вы пишете аннотацию @Inject или @Entity, компилятор генерирует дополнительный код (классы, фабрики, DAO).
Внутри Gradle Kapt работает как отдельная задача. Когда вы запускаете сборку, Gradle вызывает KaptExecution — это команда, которая запускает Kotlin-компилятор с включенным processing аннотаций. Если на этом этапе что-то идет не так (например, processor выбросил исключение или закончилась память), вы видите ту самую ошибку.
Как KaptExecution выглядит в Gradle
В файле build.gradle.kts (или build.gradle) Kapt подключается так:
plugins {
kotlin("kapt") version "1.9.0"
}
dependencies {
kapt("com.google.dagger:dagger-compiler:2.48")
}
Когда вы запускаете ./gradlew build, Gradle создает дочерний процесс Java/Kotlin, который выполняет KaptExecution. В этот момент загружаются annotation processors, парсятся аннотации и генерируются файлы в папке build/generated/source/kapt.
Основные причины ошибки KaptExecution
Ошибка может быть вызвана разными факторами. Рассмотрим самые частые сценарии.
1. Конфликт версий Kotlin и Kapt
Kapt — часть Kotlin Gradle Plugin. Если версия плагина не совпадает с версией Kotlin, processor может упасть. Например:
// Неправильно
plugins {
kotlin("jvm") version "1.8.20"
kotlin("kapt") version "1.9.0" // конфликт
}
Решение: версии должны совпадать.
2. Недостаточно памяти для annotation processing
KaptExecution запускает отдельный процесс JVM. Если вы обрабатываете много аннотаций (например, Room с десятками сущностей), может не хватить heap. В логах вы увидите OutOfMemoryError.
Решение: увеличьте память для Gradle daemon в gradle.properties:
org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=512m
kapt.use.worker.api=false
3. Баги в annotation processor
Иногда сам processor (например, старая версия Dagger или Room) содержит ошибки. Они проявляются только при определенных структурах кода.
Пример: циклическая зависимость в Dagger может вызвать StackOverflowError внутри KaptExecution.
// Пример проблемного кода
@Module
class MyModule {
@Provides
fun provideA(b: B): A = A(b)
@Provides
fun provideB(a: A): B = B(a) // циклическая зависимость
}
KaptExecution упадет с сообщением Circular dependency detected. Решение — перепроектировать граф зависимостей.
4. Проблемы с кешированием Gradle
Gradle кеширует результаты Kapt. Если вы изменили код или версию processor, но кеш не обновился, KaptExecution может выдать ошибку из-за несоответствия сгенерированных файлов.
Решение: очистить кеш:
./gradlew clean --refresh-dependencies
Как читать stacktrace ошибки KaptExecution
Когда Gradle выводит ошибку, он показывает длинный стек вызовов. Большинство разработчиков пугаются и сразу идут в Google. Но на самом деле ключевая информация находится в первых 10–15 строках.
Пример stacktrace:
A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
> Caused by: java.lang.IllegalStateException: @Entity annotated class must have a primary key
at com.example.room.processor.EntityProcessor.process(EntityProcessor.kt:42)
... 23 more
Здесь видно, что проблема в Room: одна из сущностей не имеет первичного ключа. Решение — добавить @PrimaryKey.
Пошаговый план диагностики и исправления
Когда вы видите ошибку KaptExecution, не паникуйте. Следуйте этому алгоритму.
Шаг 1. Проверьте версии Kotlin и Kapt
Убедитесь, что kotlin("jvm") и kotlin("kapt") имеют одинаковую версию. Лучше всего задать версию через переменную:
ext.kotlin_version = '1.9.0'
plugins {
kotlin("jvm") version kotlin_version
kotlin("kapt") version kotlin_version
}
Шаг 2. Включите подробные логи Kapt
Добавьте в build.gradle.kts:
kapt {
showProcessorDetails = true
useBuildCache = false
arguments {
arg("kapt.kotlin.generated", "${buildDir}/generated/source/kapt")
}
}
Это покажет, какой именно processor упал и с какой ошибкой.
Шаг 3. Проверьте совместимость processor
Если используете Room, Dagger или Moshi, проверьте, поддерживает ли их версия вашу версию Kotlin. Например, Room 2.5.x требует Kotlin 1.8+. Совместимость можно найти в документации библиотеки.
Шаг 4. Увеличьте память
Если проект большой, пропишите в gradle.properties:
org.gradle.jvmargs=-Xmx6g
kapt.use.worker.api=true
Флаг kapt.use.worker.api=true включает безопасный режим обработки.
Шаг 5. Изолируйте проблемный модуль
Если проект мультимодульный, попробуйте собрать только один модуль:
<