App Not Installed: Package Conflicts With an Existing Package
On this page
Short answer: Android only lets an APK update an installed app when both are signed with the same certificate (or the new one carries a signing lineage that links back to it). “App not installed as package conflicts with an existing package” is what the phone’s installer shows when the package name matches but the certificate does not. The fix is to sign with the key the installed copy was signed with, or to remove the old copy deliberately. It is never to weaken signature checks.
You can find out which key signed each build in a few seconds with this site’s APK & AAB analyzer, which reads the certificate in your browser without uploading the file. This guide reproduces the error on two Android emulators with APKs I built and signed myself, and shows every step with real output.
Who this is for: Android developers and testers who install their own builds by hand (from Android Studio, CI artifacts, a website or an internal store) and hit this message.
What you will learn:
- What the error means, and the exact
INSTALL_FAILED_*code behind it - How to compare the signing certificate of two APKs
- How to find the copy that is already installed, including one hidden in another user profile
- The fixes: the original keystore, Play App Signing, key rotation with a lineage
- What REA, the open-source project by morluto, can and cannot tell you here (version 6.4.0)
Only install and inspect apps you build or are authorized to test, on devices you control.
What the message really means
Every installed app is identified by its package name, and the platform remembers the certificate it was signed with. When a new APK arrives with the same package name, the package manager compares certificates. If they differ, the update is refused, because otherwise anyone could ship an “update” that takes over your app’s data.
The phone shows a friendly sentence. adb install shows the real reason. Here is what I got on an Android 14 (API 34) emulator after installing signdemo-debug-v1.apk, signed with a key whose subject is the Android Studio debug subject, and then trying to install signdemo-release-v2.apk, the same package signed with my release key:
$ adb install signdemo-debug-v1.apk
Success
$ adb install signdemo-release-v2.apk
adb: failed to install signdemo-release-v2.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package dev.example.signdemo signatures do not match newer version; ignoring!]
adb install -r (replace) failed with the same code, and an Android 16 (API 36) emulator printed exactly the same line. The higher versionCode (2 over 1) does not help. Signatures are checked regardless.
Searches for this error also turn up INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES. That one is a different problem: the APK’s own signature data is inconsistent, for example the APK was modified after signing. The fix there is to rebuild and sign as the last step. This guide is about the update conflict.
The same “App not installed” wording also covers a version downgrade, which is worth ruling out first:
$ adb install signdemo-release-v2.apk
Success
$ adb install signdemo-release-v1.apk
adb: failed to install signdemo-release-v1.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE: Downgrade detected: Update version code 1 is older than current 2]
Same key, lower versionCode. The fix there is a higher version code, not a different key.
The usual causes
- Debug build over release build, or the reverse. Android Studio signs debug builds with
~/.android/debug.keystore, which is different on every machine. Your release keystore is something else. - Play-installed copy plus a locally signed APK. With Play App Signing, Google re-signs the APKs it delivers with the app signing key. Your locally signed APK carries the upload key. To the phone, these are two different certificates.
- A new machine or CI runner. A fresh
debug.keystore, or a release keystore regenerated “with the same password”, is still a new key. - A leftover copy in another user or profile. The app looks uninstalled, but it still exists for a work profile, a secondary user or a vendor’s secure folder.
Step 1: Compare the two certificates
Open the APK & AAB analyzer and drop the first APK. The Signing section lists every signer by scheme (v1, v2, v3, v3.1) with its subject, issuer, validity and SHA-256 fingerprint. Then drop the second APK and compare.
For my two builds, the analyzer showed:
signdemo-debug-v1.apk v1, v2, v3 signer: CN=Android Debug,O=Android,C=US
SHA-256 f6046b4255cb26025a3eb6497d60afbe206d7e109e3581b40d25ffebf881207b
signdemo-release-v2.apk v1, v2, v3 signer: CN=Example Release,O=Example,C=US
SHA-256 1b9aafb13d527001813e0c2d212ff035c57c003434ceeaf705be8cc736b3f4d0
Different SHA-256 values mean a conflict. The debug build also failed check SIGN-01 (debug certificate), which is a reject on Google Play and a high risk outside it. The tool matches the subject attributes CN=Android Debug, O=Android, C=US, the subject Android Studio’s debug key uses.
The analyzer does not compare two files for you yet. Open them one after the other and compare the SHA-256 lines. The first and last few hex digits are usually enough to tell keys apart, but compare the whole value before you act on it.
Cross-check with apksigner
apksigner from the Android SDK build-tools gives the same fingerprints:
apksigner verify --print-certs signdemo-debug-v1.apk
apksigner verify --print-certs signdemo-release-v2.apk
Signer #1 certificate DN: CN=Android Debug, O=Android, C=US
Signer #1 certificate SHA-256 digest: f6046b4255cb26025a3eb6497d60afbe206d7e109e3581b40d25ffebf881207b
Signer #1 certificate DN: CN=Example Release, O=Example, C=US
Signer #1 certificate SHA-256 digest: 1b9aafb13d527001813e0c2d212ff035c57c003434ceeaf705be8cc736b3f4d0
To see which keystore a fingerprint belongs to, print the keystore entry. keytool shows the same SHA-256 with colons and in upper case:
keytool -list -v -keystore release.jks -alias release
Owner: CN=Example Release, O=Example, C=US
SHA256: 1B:9A:AF:B1:3D:52:70:01:81:3E:0C:2D:21:2F:F0:35:C5:7C:00:34:34:CE:EA:F7:05:BE:8C:C7:36:B3:F4:D0
Step 2: Get the copy that is actually installed
Often you do not have the APK that is on the phone. Pull it back. With plain adb, adb shell pm path <package> gives the device path and adb pull copies it. REA 6.4.0 wraps both and records a SHA-256 of each pulled file:
export REA_ADB_PATH="$HOME/Library/Android/sdk/platform-tools/adb"
rea pull-adb-package emulator-5582 dev.example.signdemo --output-directory /tmp/pulls --format json
rea inspect-adb-package emulator-5582 dev.example.signdemo --format json
Trimmed normalized_result fields from my run:
pull-adb-package: artifacts[0].file_name "base.apk", role "base", bytes 8538,
sha256 "cf940e49d902f4268b7cd94947b2bd4bbe96c604db30f5937db406442a0caebf"
inspect-adb-package: version_name "1.1", version_code 1,
installer_package_name "null", first_install_time "2026-10-14 13:09:35"
The pulled base.apk had the same SHA-256 as the debug APK I had installed, and the analyzer showed the debug certificate on it. If an app was installed with split APKs, pull-adb-package pulls the base and every split.
installer_package_name tells you who installed the copy. Mine says null because it came from adb install. A copy that came from Google Play names the Play Store package instead. That is your hint that the installed APK carries Play’s app signing certificate, not your upload key.
REA’s inspect-adb-package does not report the installed signing certificate. Pull the APK and read the certificate with the analyzer or apksigner.
Look for hidden copies in other users
I installed the debug build only for a secondary user (user 10) and then tried to install the release build for the main user:
$ adb install --user 10 signdemo-debug-v1.apk
Success
$ adb shell pm list packages --user 0 dev.example.signdemo
$ adb shell dumpsys package dev.example.signdemo | grep "installed="
User 0: ceDataInode=0 installed=false ...
User 10: ceDataInode=0 installed=true ...
$ adb install signdemo-release-v2.apk
adb: failed to install ...: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package dev.example.signdemo signatures do not match newer version; ignoring!]
The app list for user 0 was empty, yet the install failed. REA’s resolve-adb-packages emulator-5582 signdemo and inspect-adb-package still found the package. adb uninstall dev.example.signdemo, which removes it for all users, cleared the conflict and the release build installed. On a real phone, check the work profile and any secure folder for the app before you remove it.
Step 3: Fix it on your side
Sign with the original key
If the installed copy is your release build and you still have that keystore, sign the new build with it. Then a higher versionCode updates normally and keeps the user’s data. That is the only fix that keeps data for users who already have the app.
Debug versus release on a test device
On a test device, the cleanest fix is to uninstall the other variant and install the one you want. Accept that its app data goes with it. To keep both on one device, give debug builds their own application ID, for example applicationIdSuffix ".debug" in the Gradle debug build type, so they never collide with the release package.
If you need the test data, export it before you uninstall. For a debuggable build, adb shell run-as <package> gives you access to the app’s private files. Otherwise use the app’s own export or backup feature.
Play App Signing
If testers install from Play and also sideload your local builds, the two copies will always conflict, because Play delivers APKs signed with the app signing key. Two options work:
- Distribute test builds through Play’s testing tracks or internal app sharing, so every copy comes from Play.
- Or test locally signed builds on devices that do not have the Play version installed.
The app signing page in Play Console lists the SHA-256 of both the app signing key and the upload key. Compare those with what the analyzer shows for each APK, and you will know which key signed which copy.
Changing keys on purpose: key rotation
If you must move to a new key, APK Signature Scheme v3 supports rotation through a signing lineage. The new key is linked to the old one, so devices accept the update. I created a lineage and signed version 3 with both keys:
apksigner rotate --out lineage.bin \
--old-signer --ks release.jks --new-signer --ks release2.jks
apksigner sign --ks release.jks --next-signer --ks release2.jks \
--lineage lineage.bin --out signdemo-rotated-v3.apk aligned.apk
Installed over signdemo-release-v2.apk (old key), it gave Success on both emulators. The analyzer lists four signers for this file: v1, v2 and v3 with the old certificate (1b9aafb1…, v3 limited to SDK 24–32), and a v3.1 signer with the new certificate CN=Example Release 2026 (b39a1c85…, SDK 33 and up). apksigner verify -v --print-certs agrees, and apksigner lineage --print-certs shows Has rollback capability: false. Rotation is one-way unless you grant rollback: on the API 34 emulator, adb install -r -d signdemo-release-v2.apk (the old-key build) over the rotated version failed with INSTALL_FAILED_UPDATE_INCOMPATIBLE again.
Keep both keystores. For apps on Play, request a key upgrade in Play Console instead of rotating the app signing key yourself.
Prevent it next time
- Store the release keystore and its passwords in a secrets manager and back it up offline. A lost key cannot be recovered.
- Make CI sign with that keystore, never one generated on the runner.
- Record the release certificate SHA-256 in your release notes and compare it on every build. The same fingerprint is what Android developer verification asks you to register.
- Give debug builds their own application ID.
What REA 6.4.0 does and does not do here
rea inspect-android-packagereads the manifest, and its result sayssignature_verification: "not_performed". It does not read or compare signing certificates.rea install-adb-packageis described in its contract as keeping the device’s Failure reason. With adb 37.0.1, every failed install in my test came back as a genericunreadable_outputerror (“Analysis returned an unreadable result”), and theINSTALL_FAILED_*text was not in the output. The 6.4.0 code only parsesFailure [...]from stdout, and this adb version prints the failure to stderr and exits with a non-zero code. Use plainadb installto read the code.pull-adb-package,inspect-adb-packageandresolve-adb-packagesworked as shown above and are useful for finding and collecting the installed copy.
FAQ
Can I force the install without uninstalling? Not with a different certificate. The platform refuses the update by design. Sign with the original key, use a rotation lineage that includes it, or uninstall first.
Does a higher versionCode fix it?
No. Version codes matter for downgrades (INSTALL_FAILED_VERSION_DOWNGRADE). Certificates are checked regardless of the version.
I lost my release keystore. What now? Users of the old build cannot update in place. For an app on Play with Play App Signing, you can request an upload key reset in Play Console, because Google holds the app signing key. Outside Play, ship under the old package only if you find the key. Otherwise use a new package name, and users must install it fresh.
The analyzer shows two different certificates in one APK. That is a rotated APK: older schemes carry the old key, v3.1 the new one. It is expected after a key rotation.
Next steps
- Compare certificates and run the full pre-release check: APK & AAB analyzer
- The other common install error: “App isn’t compatible with your phone”
- Read the crash log when the build installs but crashes: adb logcat and bugreport with REA
- Inspect a pulled APK further: Android APK analysis with REA
- Reference: Sign your app, apksigner, APK signature scheme v3, REA’s DISCLAIMER.md