Fixing “Duplicate Class Found” Errors in Android

Editorial team
Dot
June 24, 2026
Technical tutorial banner titled "Fixing 'Duplicate Class Found' Errors in Android," with the subtitle "Understand why duplicate class errors occur, how to fix them, and best practices to prevent them." The graphic features a 3D Android mascot holding a wrench next to gears and a screwdriver. A smartphone in the center displays a "Duplicate Class Found" warning pop-up over lines of code, while a second cracked screen shows a warning symbol. A bottom bar lists steps to resolve the issue: Identify Causes, Fix Conflicts, Clean & Build, Prevent Future Issues, and Better Performance.

Introduction

If you have been building Android apps for some time, you have almost certainly hit a wall with this error during a Gradle build:

Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in

kotlin-stdlib-1.8.x (org.jetbrains.kotlin:kotlin-stdlib:1.8.x)
kotlin-stdlib-jdk8-1.8.x (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.x)

Or perhaps something like:

Duplicate class android.support.v4.app.Fragment found in modules

jetified-support-fragment-1.0.0 and fragment-1.x.x

Build fails. The app won’t compile. You stare at the terminal wondering what went wrong especially since everything was fine yesterday.

This guide walks you through every major cause of the “Duplicate class found” error in Android, and gives you copy-paste-ready fixes for each scenario. Whether you are a solo indie developer or part of a large team, these solutions will get your build green again.

 

Problem Statement

The Duplicate class found error is a compile-time classpath conflict. It occurs when two or more dependencies on your Gradle classpath provide the same fully-qualified Java/Kotlin class name.

Android’s build toolchain (D8 / R8) cannot decide which copy of the class to include in the final DEX output, so it fails fast with this error rather than silently picking one.

When does this typically appear?

Triggers Table
Trigger Example
Migrating from Support Library to AndroidX android.support.* vs androidx.*
Upgrading Kotlin version kotlin-stdlib vs kotlin-stdlib-jdk7/jdk8
Adding a new third-party SDK SDK bundles a library you already use
Upgrading Firebase or Google Play Services Version mismatch between BOM and explicit deps
Multi-module projects Same dependency declared in multiple modules at different versions

Note: This error only surfaces at build time — it never reaches users. But it is a hard blocker that stops every developer on your team until fixed.

 

Root Causes

Before jumping to fixes, understanding the root causes helps you pick the right solution:

  • Support Library + AndroidX Co-existence

Google replaced the old com.android.support library with androidx.* starting in AndroidX 1.0 (2018). Including both in the same project causes class conflicts because many classes were renamed (but not deleted from the old library).

  • Kotlin Stdlib Splitting (Kotlin 1.8+)

Before Kotlin 1.8.0, kotlin-stdlib-jdk7 and kotlin-stdlib-jdk8 were separate artifacts. From Kotlin 1.8.0 onwards, their content was merged into kotlin-stdlib. If your project or any dependency explicitly declares kotlin-stdlib-jdk7 or kotlin-stdlib-jdk8, Gradle pulls in the old artifacts alongside the new merged kotlin-stdlib, causing duplicates.

  • Transitive Dependency Conflicts

When Library A depends on okhttp:3.x and Library B depends on okhttp:4.x, Gradle may resolve both on the classpath. These contain overlapping classes.

  • Duplicate Declarations Across Modules

In multi-module Android projects, the same dependency can be declared in multiple modules at different versions, leading to conflicts when the final APK/AAB is assembled.

Solution & Implementation

Work through the fixes below in order. Most projects are resolved by Fix 1 or Fix 2.

Fix 1: Enable AndroidX and Jetifier

Applicable when: You are mixing com.android.support and androidx.* libraries.

Open your gradle.properties file (project root) and add:

# gradle.properties

 # Enables AndroidX artifact mapping
 android.useAndroidX=true


 # Automatically converts Support Library dependencies to AndroidX equivalents 
 android.enableJetifier=true

Then perform a full Gradle sync and rebuild.

What Jetifier does: It rewrites bytecode of legacy com.android.supportdependencies on-the-fly to use androidx.* namespaces, eliminating the class duplication.

Verification: After enabling Jetifier, run:

./gradlew :app:dependencies | grep "support"

You should see no raw com.android.support entries remaining (they will all appear as justified* versions).

Fix 2: Exclude Duplicate Kotlin Stdlib Classes

kotlin-stdlib-1.8.x and kotlin-stdlib-jdk8-1.8.x

Applicable when: You see errors like:

Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules

Open your app-level build.gradle (or build.gradle.kts) and add a resolution strategy:

Groovy DSL (build.gradle):

// app/build.gradle

dependencies {
  // ... your existing dependencies


  // Force Kotlin stdlib consolidation (Kotlin 1.8+ merged jdk7/jdk8 into stdlib)
  constraints {
      implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7") {
          version {
              require "1.8.0"
          }
          because "kotlin-stdlib-jdk7 is merged into kotlin-stdlib since 1.8.0"
      }
      implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") {
          version {
              require "1.8.0"
          }
          because "kotlin-stdlib-jdk8 is merged into kotlin-stdlib since 1.8.0"
      }
  }
}

Kotlin DSL (build.gradle.kts):

// app/build.gradle.kts

 dependencies {
   // ... your existing dependencies


  constraints {
      implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7") {
          version { require("1.8.0") }
          because("kotlin-stdlib-jdk7 is merged into kotlin-stdlib since 1.8.0")
      }
      implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") {
          version { require("1.8.0") }
          because("kotlin-stdlib-jdk8 is merged into kotlin-stdlib since 1.8.0")
       }
   }
 } 

Alternatively, add this to your root-level build.gradle to apply it globally across all modules:

 subprojects {
  configurations.all {
      resolutionStrategy.eachDependency { DependencyResolveDetails details ->
          if (details.requested.group == 'org.jetbrains.kotlin') {
              details.useVersion '1.9.23' // pin to your project's Kotlin version
              details.because 'Unify all Kotlin stdlib artifacts to avoid duplicate classes'
          }
      }
  }
} 

Fix 3: Use Gradle Resolution Strategy

Applicable when: Multiple libraries pull in different versions of the same dependency, and you need to force a single version across the board.

// app/build.gradle

android {
   // ...
 }


 configurations.all {
   resolutionStrategy {
       // Force a single version of OkHttp across all transitive dependencies
       force 'com.squareup.okhttp3:okhttp:4.12.0'
       force 'com.squareup.okhttp3:logging-interceptor:4.12.0'
 
       // Fail the build if two different versions of the same dependency are found
       // (useful during development to catch conflicts early)
       failOnVersionConflict()
    }
 }

Tip: Use failOnVersionConflict() in development builds to surface conflicts early, but remove it before production builds if you have transitive deps you cannot control.

Fix 4: Exclude Transitive Dependencies

Applicable when: A specific third-party library bundles a dependency you already declare, causing a direct duplicate.

Groovy DSL:

// app/build.gradle

dependencies {
    implementation('com.some.third-party:sdk:2.0.0') {
      // Exclude the bundled OkHttp since we manage our own version
      exclude group: 'com.squareup.okhttp3', module: 'okhttp'
  }


   // Our own explicitly managed version
   implementation 'com.squareup.okhttp3:okhttp:4.12.0'
 }

Kotlin DSL:

// app/build.gradle.kts

dependencies {
  implementation("com.some.third-party:sdk:2.0.0") {
      // Exclude the bundled OkHttp since we manage our own version
      exclude(group = "com.squareup0.okhttp3", module = "okhttp")
  }


   // Our own explicitly managed version
   implementation("com.squareup.okhttp3:okhttp:4.12.0")
 }

To exclude a dependency globally from all configurations:

// root build.gradle or app/build.gradle

 configurations.all {
   exclude group: 'com.android.support', module: 'support-compat'
 } 

Fix 5: Use BOM (Bill of Materials) for Firebase / Compose

Applicable when: You are using Firebase, Jetpack Compose, or other Google libraries and manually specifying versions that conflict.

A BOM lets a single version coordinate all related library versions automatically — no more version mismatch duplicates.

Firebase BOM (recommended for all Firebase projects):

// app/build.gradle

 dependencies {
   // Import the Firebase BOM — manages all Firebase library versions
   implementation platform('com.google.firebase:firebase-bom:33.1.0')


   // Declare Firebase libraries WITHOUT version numbers
   implementation 'com.google.firebase:firebase-analytics'
   implementation 'com.google.firebase:firebase-crashlytics'
   implementation 'com.google.firebase:firebase-messaging'
 }

Jetpack Compose BOM:

// app/build.gradle

dependencies {
   // Import the Compose BOM
   implementation platform('androidx.compose:compose-bom:2024.05.00')


   // Declare Compose libraries WITHOUT version numbers
   implementation 'androidx.compose.ui:ui'
   implementation 'androidx.compose.material3:material3'
   implementation 'androidx.compose.ui:ui-tooling-preview'
 }

Why BOM works: The BOM defines a tested and compatible set of versions for all related libraries. Declaring a version yourself on top of a BOM import will always win — so if you add a BOM, remove explicit versions from BOM-managed libraries.

Fix 6: Run Dependency Insight Command

Applicable when: You are not sure which library is causing the conflict and need to diagnose before fixing.

Use the Gradle dependencyInsight task to trace exactly where a dependency is coming from:

# Find who is pulling in kotlin-stdlib-jdk8
 ./gradlew :app:dependencyInsight --dependency kotlin-stdlib-jdk8 --configurationreleaseRuntimeClasspath


 # Find who is pulling in a support library
 ./gradlew :app:dependencyInsight --dependency support-fragment --configurationreleaseRuntimeClasspath


  # Print the full dependency tree
 ./gradlew :app:dependencies --configuration releaseRuntimeClasspath > deps.txt

Reading the output:

 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21 (selected by rule)
 \--- com.some.sdk:analytics:1.0.0
  \--- releaseRuntimeClasspath

This tells you com.some.sdk:analytics:1.0.0 is pulling in an old kotlin-stdlib-jdk8. You can now either upgrade that SDK or apply an exclusion (Fix 4).

Key Takeaways

Scenarios and Recommended Fixes Table
Scenario Recommended Fix
Support Library + AndroidX conflict Fix 1 — Enable useAndroidX +enableJetifier
Kotlin stdlib duplicate (Kotlin 1.8+) Fix 2 — Dependency constraints
General version conflict across libs Fix 3 — Resolution strategy with force
Third-party SDK bundles a duplicate Fix 4 — Exclude transitive dependency
Firebase / Compose version mismatch Fix 5 — Use BOM
Unknown source of conflict Fix 6 — dependencyInsight to diagnose

Quick Reference Checklist:

  • Check gradle.properties for android.useAndroidX=true and android.enableJetifier=true
  • Pin Kotlin stdlib version using dependency constraints if on Kotlin 1.8+
  • Use ./gradlew :app:dependencies to inspect the full dependency tree
  • Replace explicit Firebase/Compose versions with their respective BOMs
  • Exclude duplicate transitive dependencies per-library or globally
  • Run a clean build after any fix: ./gradlew clean assembleDebug

Pro Tip: Always run ./gradlew clean before rebuilding after dependency changes. Gradle’s

incremental build cache can sometimes mask whether a fix actually worked.

 

Reference Links

FAQ’s

No items found.

Actionable Insights,
Straight to Your Inbox

Subscribe to our newsletter to get useful tutorials , webinars,use cases, and step-by-step guides from industry experts

Start Pushing Real-Time App Updates Today
Try AppsOnAir for Free
Stay Uptodate