Play Console rejects uploads with short messages that rarely say what to change. Here is what each of the common ones actually means.
"Version code N has already been used"
Every upload needs a versionCode higher than any you have ever uploaded — including builds you later discarded, and builds on other tracks. The number is global to the app and never resets.
android {
defaultConfig {
versionCode 12 // must increase, always
versionName "1.3.0" // free text, shown to users
}
}
versionName is cosmetic. versionCode is the one Play tracks. If you cannot remember the highest used, Play Console → App bundle explorer lists every version you have uploaded.
"Your app is using permissions that require a privacy policy"
Declare a privacy policy URL under App content. It must be public, load without a login, not be editable by visitors, and mention your app by name. Generate one that matches your SDKs with the privacy policy generator.
"The package name is already in use" / "does not match"
Your applicationId is permanent once published. It cannot be changed, reused after deletion, or claimed if someone else has it. If you shipped with com.example.myapp, you are living with it — the only way out is a new listing and losing your installs.
The mismatch version of this error means the bundle's applicationId differs from the one the Play Console entry expects. Check for build flavours appending a suffix:
// this produces com.myapp.debug, which Play will reject
buildTypes {
debug { applicationIdSuffix ".debug" }
}
"Your Android App Bundle is signed with the wrong key"
You signed with a different keystore than the upload key registered for this app. Common causes: a new machine, a regenerated keystore, or CI signing with a different secret.
Verify which key you signed with:
keytool -printcert -jarfile app-release.aab
Compare the SHA-1 to the upload certificate in Play Console → Test and release → Setup → App signing. If you have genuinely lost the keystore and are enrolled in Play App Signing, you can request an upload key reset from that page — that is the safety net Play App Signing exists to provide. The keystore SHA-1 helper builds the right command for your OS.
"You uploaded a debuggable APK or Android App Bundle"
android:debuggable="true" reached the release build. Usually it is hardcoded in the manifest rather than left to the build type. Remove it from AndroidManifest.xml entirely and let Gradle set it per build type.
"You uploaded an APK or Android App Bundle with an invalid signature"
Almost always a v1-only signature on a build that needs v2 or later. Ensure your signing config enables the modern schemes:
signingConfigs {
release {
// ...
enableV1Signing true
enableV2Signing true
}
}
"Your app currently targets API level N and must target at least M"
Play enforces a minimum targetSdkVersion for new apps and updates, and raises it annually. Bump targetSdk in build.gradle — but do not just change the number and ship. Each API level brings behaviour changes (background limits, storage scoping, permission changes) that can break the app at runtime. Read the behaviour-change notes for every level you skip, and test.
"Upload failed: you need to use a different version code for your APK because you already have one with version code N"
The same problem as the first error, hit on a different track. Tracks share one version code space — an internal testing build at code 12 blocks production from using 12.
A habit that prevents most of these
Derive the version code from something that cannot repeat, rather than editing it by hand:
def buildNumber = System.getenv("BUILD_NUMBER") ?: "1"
versionCode buildNumber.toInteger()
And upload to internal testing first, every time. It runs the same validation as production but costs nothing if it fails.