fix(android): skip explicit Kotlin plugin when AGP provides built-in Kotlin - #1394
fix(android): skip explicit Kotlin plugin when AGP provides built-in Kotlin#1394gabrieldonadel wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped to conditional plugin application and preserves AGP <= 8 behavior while preventing the known AGP 9+ configuration failure.
Pull request overview
This PR prevents Android builds from failing on Android Gradle Plugin (AGP) 9+ by avoiding an explicit kotlin-android plugin apply when AGP’s built-in Kotlin support is already enabled, while preserving the existing behavior for AGP 8 and older.
Changes:
- Added a
shouldApplyKotlinPlugin()guard that checks the AGP major version andandroid.builtInKotlinto decide whether to applykotlin-android. - Replaced unconditional
apply plugin: 'kotlin-android'with a conditional apply in the affected package Gradle scripts.
File summaries
| File | Description |
|---|---|
| packages/core/android/build.gradle | Conditionally applies kotlin-android to avoid AGP 9 built-in Kotlin collisions. |
| packages/internal-testing-tools/android/build.gradle | Adds AGP/version + property gate around kotlin-android plugin application. |
| packages/react-native-session-replay/android/build.gradle | Avoids double-applying Kotlin on AGP 9+ by guarding the Kotlin plugin apply. |
| packages/react-native-webview/android/build.gradle | Adds the same conditional Kotlin plugin apply to prevent configuration-phase failures on AGP 9+. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…Kotlin AGP 9 enables built-in Kotlin by default and applies the Kotlin plugin itself. Applying it again fails configuration with "Cannot add extension with name 'kotlin'". Guard the explicit apply so it only runs when AGP is not providing Kotlin: AGP 8 and older, or AGP 9 with android.builtInKotlin=false. AGP 10 removes that opt-out, so built-in Kotlin is always active there and the explicit apply must never run.
fcbc2a7 to
82e70b3
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The guard is consistent with existing AGP version checks in these scripts and prevents the known AGP 9+ Kotlin plugin double-application failure without affecting AGP ≤ 8 behavior.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0 new
- Review effort level: Lite
Problem
Android Gradle Plugin 9 ships built-in Kotlin support and enables it by default, so AGP
applies the Kotlin plugin itself. When a library also applies
kotlin-androidexplicitly, thetwo collide and configuration fails before anything compiles:
The apply is unconditional in these files, so on an AGP 9 project they cannot be built
at all. There is no consumer-side workaround short of patching the file — setting
android.builtInKotlin=falseproject-wide just to build one dependency is not areasonable ask, and that escape hatch is removed in AGP 10.
Change
Keep the explicit apply, but skip it when AGP is already providing Kotlin:
Files changed:
packages/core/android/build.gradlepackages/internal-testing-tools/android/build.gradlepackages/react-native-session-replay/android/build.gradlepackages/react-native-webview/android/build.gradleWhy the condition has this shape
Both halves are load-bearing:
AGP nothing else applies the Kotlin plugin, so skipping would break the build in the
opposite direction.
android.builtInKotlindefaults to on in AGP 9, soonly an explicit
falsemeans "AGP is not providing Kotlin, apply it yourself". Thismirrors AGP's own default.
android.builtInKotlinfalsetruefalsecom.android.Version.ANDROID_GRADLE_PLUGIN_VERSIONrequires no new plugin resolution,and the apply already happens after
com.android.library, so AGP is on the classpath.What I verified, and what I did not
9.2.1 and Gradle 9.4.1:
:app:assembleDebugsucceeds both with-Pandroid.newDsl=true -Pandroid.builtInKotlin=trueand with both flags off. Sameguard, both configurations green.
Phases.CONVERSION.construction, since
shouldApplyKotlinPlugin()short-circuits totruethere — but aCI run is the real confirmation and I could not do that from outside.
Found while sweeping 157 popular React Native libraries for AGP 9 new-DSL compatibility.
34 failed with the new DSL enabled, and 29 of those failed on exactly this — it is the
most common blocker by a wide margin.