When you upload an AAB to Google Play, you may see this error:
Version code has already been used.
This happens when the versionCode inside the new AAB matches a value that has already been used for the same app.
What is versionCode?
versionCode is an integer Android and Google Play use to determine the update order of app builds.
android {
defaultConfig {
versionCode = 43
versionName = "1.4.0"
}
}
As a general rule, every new release should use a value higher than the previous one.
First release: 1
Next release: 2
Following release: 3
How versionCode differs from versionName
| Field | versionCode | versionName |
|---|---|---|
| Purpose | Internal update ordering | User-visible version label |
| Format | Integer | String |
| Example | 43 | 1.4.0 |
| On update | Must increase | Can follow your chosen naming scheme |
Changing versionName alone does not create a new update if versionCode stays the same.
Why the duplicate error appears
The value was uploaded before
A value used in a previous upload may remain unavailable even if the release was later discarded or left as a draft. The safer approach is to assign a new, higher value.
Another track already used it
Internal, closed, open, and production tracks share the same versionCode space for one Play app.
versionCode 50 was already uploaded to internal testing
→ 50 cannot be uploaded again to closed testing
You selected an old AAB
When several build artifacts exist, it is easy to upload a file generated before the version was changed.
Useful safeguards include:
- Include the version code in the artifact name
- Check the generated timestamp
- Delete old output directories before rebuilding
- Confirm the selected build variant
CI and local builds generated the same number
If a local build and CI both generate versionCode 43, only the first uploaded artifact succeeds.
Use one authoritative numbering strategy across local and automated builds.
Change the value in Android Studio
Kotlin DSL:
android {
defaultConfig {
versionCode = 44
versionName = "1.4.1"
}
}
Groovy:
android {
defaultConfig {
versionCode 44
versionName "1.4.1"
}
}
After changing the value, build a new release AAB.
./gradlew bundleRelease
Change the value in Flutter
The version in pubspec.yaml uses this format:
version: 1.4.1+44
1.4.1becomesversionName44becomesversionCode
Build the App Bundle:
flutter build appbundle
Or specify both values directly:
flutter build appbundle \
--build-name=1.4.1 \
--build-number=44
Change the value in Expo or EAS
In Expo, check the app config and EAS version-management settings.
{
"expo": {
"version": "1.4.1",
"android": {
"versionCode": 44
}
}
}
If EAS increments the value remotely, decide whether the remote configuration or the local app config is authoritative. Avoid letting both systems assign values independently.
Numbering strategies
Simple sequence
1, 2, 3, 4...
This is often the clearest approach for a small app or an individual developer.
Date-based numbering
2026080301
If you produce multiple builds in one day, add a per-day sequence. Also keep Android’s maximum supported value in mind.
CI build number
1000 + CI_RUN_NUMBER
When multiple branches build at the same time, design the formula so they cannot produce duplicate values.
Recommended handling across multiple tracks
You can reserve fixed ranges for different tracks, but that often makes promotion and release management harder.
A single increasing sequence across all tracks is usually easier to understand.
42 internal test
43 closed test
44 corrected closed-test build
45 production candidate
When Play Console allows the same artifact to be promoted to another track, consider promotion instead of rebuilding the same version with another number.
Can versionCode be lowered?
A normal update cannot install a lower versionCode over a higher one already received by the device.
Using an unnecessarily large number during testing also means later production builds must use an even larger value.
Check the artifact before upload
You can inspect project properties with Gradle:
./gradlew :app:properties
You can also inspect the generated bundle with Android Studio, bundletool, or Play Console’s App Bundle Explorer.
Confirm:
versionCodeversionNameapplicationId- Signing certificate
- Build variant
- Generation time
Summary
To prevent duplicate versionCode errors:
- Use a new, higher integer for every uploaded build
- Do not confuse
versionCodewithversionName - Avoid reuse across all test and production tracks
- Do not upload an older AAB by mistake
- Use one numbering rule for CI and local builds
- Inspect the actual artifact before uploading
If the next error concerns signing, see Play App Signing and the Upload Key.
Primary sources
Official references
Check the linked official documentation before a production release.
Continue reading
Related guides
TestCrew
Find testers through mutual testing
Test other Android apps, provide useful feedback, and use earned credits to recruit testers for your own Google Play closed test.
Learn how TestCrew works