Fix "The number of method references in a .dex file cannot exceed 64K" (DexIndexOverflowException)

intermediate๐Ÿ“ฑ Android2026-05-06| Android Studio (any version), Gradle 3.xโ€“8.x, Android API 19โ€“34, Java/Kotlin projects

Error Message

com.android.dex.DexIndexOverflowException: method ID not in [0, ffff]: 65536
#gradle#multidex#android-studio#build-error

TL;DR

Your app โ€” including every library it drags in โ€” has crossed 65,536 method references. That's the hard ceiling of a single DEX file. The fix depends on your minSdk:

  • minSdk < 21: Enable MultiDex in build.gradle and extend MultiDexApplication.
  • minSdk โ‰ฅ 21: ART handles multiple DEX files natively. Set multiDexEnabled true and you're done.
  • Either way, enable R8 shrinking. It'll cut your reference count significantly in release builds.

The exact error

AGPBI: {"kind":"error","text":"The number of method references in a .dex file cannot exceed 64K.",
"sources":[{}],"tool":"Dexer"}
...
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

This blows up during the Gradle build โ€” specifically at the dexing step, after compilation has already succeeded. It usually surfaces right after you add a heavy dependency: Firebase, Google Play Services, or a full Retrofit + OkHttp stack are the usual suspects.

Why it happens

The DEX format uses a 16-bit index to reference methods. That caps out at exactly 65,536 (0xFFFF + 1) โ€” no exceptions. Modern apps blow past this faster than you'd expect. Google Play Services alone used to consume around 20,000 references; add Retrofit, Room, and a couple of Firebase modules and you're over the limit before you've written a single line of business logic.

Want to see where you stand before the build fails? Install the dexcount plugin:

# build.gradle (project level)
buildscript {
    dependencies {
        classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:4.0.0'
    }
}

# build.gradle (app level)
apply plugin: 'com.getkeepsafe.dexcount'

Then run ./gradlew assembleDebug โ€” the plugin prints a per-package method count breakdown in the build output.

Fix 1 โ€” minSdk โ‰ฅ 21 (simplest path)

ART (Android 5.0+) loads multiple DEX files out of the box. One flag is all you need:

// app/build.gradle
android {
    defaultConfig {
        minSdk 21
        multiDexEnabled true
    }
}

No extra dependency. No Application class changes. Sync and rebuild.

Fix 2 โ€” minSdk < 21 (legacy support)

Older Dalvik devices need the MultiDex support library wired in manually.

Step 1 โ€” add the dependency:

// app/build.gradle
android {
    defaultConfig {
        minSdk 16
        multiDexEnabled true
    }
}

dependencies {
    implementation 'androidx.multidex:multidex:2.0.1'
}

Step 2 โ€” update your Application class.

Option A โ€” extend MultiDexApplication directly (the easiest route if you don't already have a custom base):

// Kotlin
class MyApp : MultiDexApplication() {
    // your existing code
}

// Java
public class MyApp extends MultiDexApplication {
    // your existing code
}

Option B โ€” override attachBaseContext instead (use this if you're already extending something else and can't change the parent):

// Kotlin
class MyApp : SomeOtherBaseApp() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

// Java
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

Step 3 โ€” register in AndroidManifest.xml if you're not already using the default Application:

<application
    android:name=".MyApp"
    ...>

Fix 3 โ€” shrink with R8 (do this regardless of which fix you chose)

MultiDex gets the build passing. But a bloated method count still hurts โ€” on Android 4.x, loading multiple DEX files at cold start can add 200โ€“500ms of extra startup time. R8 strips out dead code before it ever reaches the DEX stage:

// app/build.gradle
android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                         'proguard-rules.pro'
        }
        debug {
            // Enable here too if you're sitting close to the 64K limit
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                         'proguard-rules.pro'
        }
    }
}

R8 is the default in AGP 3.4+. On older setups, add this line to gradle.properties:

android.enableR8=true

Fix 4 โ€” audit your dependencies

Sometimes the real problem is that you're importing far more than you actually use. A few common culprits:

  • Google Play Services monolith: com.google.android.gms:play-services pulls in everything (~36K references). Import only what you need โ€” play-services-maps for Maps, play-services-auth for sign-in, etc.
  • Duplicate transitive deps: Run ./gradlew app:dependencies and look for the same library appearing at multiple versions. Each duplicate adds to the count.
  • Old support libraries: If you're still on com.android.support, migrating to AndroidX usually trims your count โ€” the rewritten artifacts are leaner.
# Full dependency tree for the release build
./gradlew app:dependencies --configuration releaseRuntimeClasspath

# Per-package method count (requires dexcount plugin)
./gradlew assembleDebug

Verify the fix worked

  • Run ./gradlew assembleDebug โ€” the DexIndexOverflowException should be gone.
  • Check the build output for 1 DEX file written or 2 DEX files written to confirm MultiDex kicked in.
  • Test on an Android 4.x device or emulator (if you support pre-21) and make sure the app launches without ClassNotFoundException.
  • Open Build โ†’ Analyze APK in Android Studio to inspect DEX sizes and method counts by package.

Common gotchas after enabling MultiDex

  • Slow cold start on Android < 5.0: The first launch extracts secondary DEX files from the APK โ€” this can take 2โ€“5 seconds on low-end hardware. Use a splash screen or defer initialization to hide the lag.
  • ClassNotFoundException at runtime: Classes that load before the Application class (custom ContentProviders, for example) might land in a secondary DEX. Pin them to the primary DEX using multiDexKeepProguard or multiDexKeepFile.
  • Incremental builds still failing: Stale DEX caches can cause phantom errors after you add MultiDex. Run ./gradlew clean and do a full rebuild.
# Pin a class to the primary DEX:
# app/build.gradle
android {
    defaultConfig {
        multiDexEnabled true
        multiDexKeepFile file('multidex-config.txt')
    }
}

# multidex-config.txt
com/example/MyContentProviderHelper.class

Related Error Notes