Mr.AndroidShin / Dev Tools

Debugging log · Build

"More than one file found with OS independent path 'META-INF/…'"

I added a networking library to a project that already had a couple of others, and the build got all the way to packaging before failing over a file I'd never heard of, buried in META-INF. The code was fine; two dependencies just happened to ship the same bookkeeping file, and the packager didn't know which one to keep.

The short version: two of your dependencies each include a file at the same path inside META-INF/ (a license, a Kotlin module file, a service descriptor). The APK can only contain one copy, so packaging fails. Tell AGP how to resolve it in the packaging { resources { } } block — usually pickFirst or excludes.

The error

2 files found with path 'META-INF/DEPENDENCIES' from inputs:
 - .../okhttp-x.y.z.jar
 - .../some-other-lib.jar
More than one file was found with OS independent path
'META-INF/DEPENDENCIES'.
Execution failed for task ':app:mergeDebugJavaResource'.

The path varies — common ones are META-INF/DEPENDENCIES, META-INF/LICENSE, META-INF/NOTICE, *.kotlin_module, and META-INF/*.version — but the shape is always the same: two inputs, one destination.

Why this happens

Libraries bundle metadata under META-INF/: license texts, notices, Kotlin module descriptors, service-loader files. When two dependencies each carry a file at the identical path, the resource-merge step has a genuine collision. It won't silently pick one for you, because in some cases (like service-loader registrations) picking the wrong one would break behavior. So it stops and asks you to decide.

Fix 1 — exclude the duplicate

If the file is inert metadata (a license or notice you don't ship), just drop it from the APK:

android {
    packaging {
        resources {
            excludes += "/META-INF/DEPENDENCIES"
            excludes += "/META-INF/LICENSE*"
            excludes += "/META-INF/NOTICE*"
        }
    }
}

This is the right choice for pure documentation files — they have no runtime purpose in your app.

Fix 2 — pickFirst when the file matters

For files that need to exist but where any one copy is fine (some native libs, certain descriptors), keep the first and ignore the rest:

android {
    packaging {
        resources {
            pickFirsts += "/META-INF/*.kotlin_module"
        }
        // for native duplicates:
        jniLibs {
            pickFirsts += "**/libc++_shared.so"
        }
    }
}

Be careful with META-INF/services/ files — these register implementations (ServiceLoader). Blindly pickFirst-ing them can drop a registration and cause a subtle runtime failure. If a duplicate is under services/, check whether both need merging rather than discarding one.

Older AGP syntax

On older Android Gradle Plugin versions the block was named differently. If packaging { } isn't recognized, you're on an older AGP and the equivalent is:

android {
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        pickFirst 'META-INF/*.kotlin_module'
    }
}

Same idea, older names. Upgrading AGP eventually moves you to the packaging { resources { } } form.

Before you exclude — is the duplicate a symptom?

Sometimes the collision is really two versions of the same library pulled in transitively. If the two inputs are different versions of one artifact, the cleaner fix is to align the versions (or exclude the transitive duplicate) rather than paper over it in packaging. A single duplicated META-INF file can be the visible tip of a dependency-graph problem.

Paths above are the common ones — match the exact path your own error prints.