## TL;DR
Increase the Android versionCode to a value higher than any ever uploaded to Google Play, rebuild the bundle, and upload again. Play never accepts a repeated or lower version code on any track, including codes used by deleted drafts. Set the new code in the Gradle build file or CI, confirm it inside the built bundle with bundletool or the Play Console upload preview, then release.

```text
version code has already been used
```

## Use this when
- Play Console or fastlane supply rejects the upload with this message.
- You rebuilt a release without bumping the version code.
- A CI job reused a cached version code from a previous run.

## Not for this skill when
- The error is about version name instead of version code. Version names are free text and can repeat.
- You need to reuse a code from a different app. Codes are per app and never transferable.

## Steps
1. Open Play Console, All apps, your app, and check the highest version code across production, testing tracks and saved drafts. Verify: you know the maximum code already used, including drafts
2. Set versionCode in the app-level Gradle file or your CI versioning step to at least one above that maximum. Verify: the build configuration shows the new integer and no flavour overrides it back down
3. Rebuild the release bundle from clean so no stale outputs carry the old code. Verify: the new AAB file timestamp is current and the build log shows the release task ran
4. Inspect the built bundle manifest with bundletool or Android Studio APK Analyzer to read the embedded version code. Verify: the tool reports the intended new version code
5. Upload the bundle to the target track and read the Console review summary before saving. Verify: Console accepts the artefact and shows the new code with no duplicate warning
6. Make CI derive the code from a monotonic source such as the build number or commit count so the collision cannot recur. Verify: two consecutive CI builds produce different, increasing codes
7. Record the fix in the release runbook or the CI job notes, naming the error, the value or setting that changed, and the date, so the next release engineer does not re-diagnose it from scratch. Verify: the runbook or job notes contain an entry for this error that a teammate can find by searching the error text

## Why it happens
Google Play treats versionCode as the permanent ordering key for an app. Every upload, even to internal testing or as a draft that was later discarded, burns that integer forever. Developers hit this when a hotfix branch keeps an old code, or when manual and CI builds share a hardcoded value.

In practice this failure is rarely a one-off. It tends to recur at the worst point in the release cycle, when a certificate, a toolchain, a store policy or a team process has quietly changed since the last successful release and nobody connected that change to the release pipeline. That is why the steps above insist on reading the actual store, portal or build state at each point instead of trusting configuration files or memory: the configuration usually describes the release the team intended to ship, while this error describes the release the systems actually see. Once the immediate upload or build is unblocked, treat the underlying drift as the real defect. Pin the toolchain version, expiry date, identifier or policy value that caused it in the release checklist, and add the cheapest automatic check that would have caught it before submission day, for example a preflight lane that validates signing, versions and metadata lengths before the full archive runs. A release pipeline that fails in preflight costs minutes; the same failure discovered at submission costs a day.

## Variants and edge cases
### version code already used Play Console upload
The Console-side phrasing of the same collision. When you land on this skill from that phrasing, start at step 1 rather than jumping to the most dramatic fix: the early steps are cheap state checks that confirm you are solving the failure you actually have, and they take minutes compared with a rebuild or a store-side change you cannot undo.
### fastlane supply version code has already been used
Fix the Gradle or CI value; supply cannot override a burned code. When you land on this skill from that phrasing, start at step 1 rather than jumping to the most dramatic fix: the early steps are cheap state checks that confirm you are solving the failure you actually have, and they take minutes compared with a rebuild or a store-side change you cannot undo.
### Edge case: multi-APK and bundles
Each split historically needed distinct codes. With bundles Play derives codes, but the base module code still must exceed all previous uploads. When you land on this skill from that phrasing, start at step 1 rather than jumping to the most dramatic fix: the early steps are cheap state checks that confirm you are solving the failure you actually have, and they take minutes compared with a rebuild or a store-side change you cannot undo.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_GdDoOv-PvFEbIq5B9teWbQ
