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.gradleand extendMultiDexApplication. - minSdk โฅ 21: ART handles multiple DEX files natively. Set
multiDexEnabled trueand 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-servicespulls in everything (~36K references). Import only what you need โplay-services-mapsfor Maps,play-services-authfor sign-in, etc. - Duplicate transitive deps: Run
./gradlew app:dependenciesand 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 writtenor2 DEX files writtento 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
multiDexKeepProguardormultiDexKeepFile. - Incremental builds still failing: Stale DEX caches can cause phantom errors after you add MultiDex. Run
./gradlew cleanand 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

