fix(android): skip explicit Kotlin plugin when AGP registers the kotlin extension - #384
Conversation
…in extension AGP 9 ships built-in Kotlin support and registers the kotlin extension itself. Applying the Kotlin plugin again fails configuration with "Cannot add extension with name 'kotlin'". Check for the extension directly, which needs no AGP version table and covers AGP 10, where the android.builtInKotlin opt-out is removed.
PR SummaryLow Risk Overview In Reviewed by Cursor Bugbot for commit 8f5bc62. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped, matches the stated AGP 9+ failure mode, and the guard is placed after com.android.library where the extension would already be registered.
Pull request overview
Updates the Android Gradle build script to avoid a configuration-time conflict on Android Gradle Plugin (AGP) 9+ where AGP registers the kotlin extension itself, causing an explicit kotlin-android apply to fail.
Changes:
- Conditionally applies
kotlin-androidonly when thekotlinextension is not already registered. - Adds an explanatory comment describing the AGP 9+ behavior and why the guard exists.
File summaries
| File | Description |
|---|---|
android/build.gradle |
Guards apply plugin: 'kotlin-android' behind an extensions.findByName('kotlin') check to prevent AGP 9+ extension collisions. |
Review details
- Files reviewed: 1/1 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.
Problem
Android Gradle Plugin 9 ships built-in Kotlin support and enables it by default, so
AGP registers the
kotlinextension itself. When a library also applieskotlin-androidexplicitly, the two collide and configuration fails before anything compiles. AGP
words it two ways, both the same problem:
The apply is unconditional in this module, so on an AGP 9 project this 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
Apply the plugin only when nothing has registered the
kotlinextension yet:Files changed:
android/build.gradleThis tests the condition that actually fails, so there is no AGP version table to
keep in sync, and it covers AGP 10 — where the
android.builtInKotlinopt-out isremoved — without a special case.
android.builtInKotlinkotlinextensionfalsetruefalseThe guard sits after
apply plugin: 'com.android.library'in every file it touches,so AGP has already registered its extensions by the time it runs. I checked that
ordering per file rather than assuming it.
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.the flags off,
compileDebugKotlinruns from the explicitly applied plugin; withthem on the build completes without it.
Phases.CONVERSIONsyntax check.Where this came from
A sweep of 1000 popular React Native libraries against the AGP 9 defaults. 281 failed
with the new DSL enabled, and 269 of those failed on exactly this collision — by
far the most common blocker. Affects
react-native-mparticlehere.The same guard shape was accepted in
RevenueCat/react-native-purchases#1934,
at that maintainer's suggestion.