Skip to content

fix(android): skip explicit Kotlin plugin when AGP provides built-in Kotlin - #1394

Open
gabrieldonadel wants to merge 1 commit into
DataDog:developfrom
gabrieldonadel:fix/agp9-built-in-kotlin
Open

fix(android): skip explicit Kotlin plugin when AGP provides built-in Kotlin#1394
gabrieldonadel wants to merge 1 commit into
DataDog:developfrom
gabrieldonadel:fix/agp9-built-in-kotlin

Conversation

@gabrieldonadel

Copy link
Copy Markdown

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-android explicitly, the
two collide and configuration fails before anything compiles:

> Failed to apply plugin 'kotlin-android'.
   > Cannot add extension with name 'kotlin', as there is an extension already registered with that name.

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=false project-wide just to build one dependency is not a
reasonable ask, and that escape hatch is removed in AGP 10.

Change

Keep the explicit apply, but skip it when AGP is already providing Kotlin:

def shouldApplyKotlinPlugin() {
    def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger()
    if (agpMajor <= 8) {
        return true
    }
    def propertyVal = providers.gradleProperty("android.builtInKotlin").orNull
    def builtInKotlinEnabled = propertyVal != null ? propertyVal.toBoolean() : true
    return !builtInKotlinEnabled
}

if (shouldApplyKotlinPlugin()) {
    apply plugin: 'kotlin-android'
}

Files changed:

  • packages/core/android/build.gradle
  • packages/internal-testing-tools/android/build.gradle
  • packages/react-native-session-replay/android/build.gradle
  • packages/react-native-webview/android/build.gradle

Why the condition has this shape

Both halves are load-bearing:

  • AGP 8 and older always apply. Built-in Kotlin only exists from AGP 9.0. On older
    AGP nothing else applies the Kotlin plugin, so skipping would break the build in the
    opposite direction.
  • Absent is treated as enabled. android.builtInKotlin defaults to on in AGP 9, so
    only an explicit false means "AGP is not providing Kotlin, apply it yourself". This
    mirrors AGP's own default.
AGP android.builtInKotlin explicit apply
8.x unset or false yes (unchanged)
9.x unset no — AGP provides it
9.x true no — AGP provides it
9.x false yes — consumer opted out

com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION requires 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

  • Verified end to end on a real Expo SDK 58 / React Native 0.87 project with AGP
    9.2.1 and Gradle 9.4.1: :app:assembleDebug succeeds both with
    -Pandroid.newDsl=true -Pandroid.builtInKotlin=true and with both flags off. Same
    guard, both configurations green.
  • Syntax-checked these files with Groovy's Phases.CONVERSION.
  • Not run: this repo's own CI or example app. The AGP <= 8 path is unchanged by
    construction, since shouldApplyKotlinPlugin() short-circuits to true there — but a
    CI 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.

Copilot AI lite review requested due to automatic review settings September 2, 2026 20:35
@gabrieldonadel
gabrieldonadel requested a review from a team as a code owner September 2, 2026 20:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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 and android.builtInKotlin to decide whether to apply kotlin-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.
@gabrieldonadel
gabrieldonadel force-pushed the fix/agp9-built-in-kotlin branch from fcbc2a7 to 82e70b3 Compare September 2, 2026 21:01
Copilot AI review requested due to automatic review settings September 2, 2026 21:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants