Android · build & submit

Version code N has already been used. Try another version code.

Version code 1 has already been used. Try another version code
APK specifies a version code that has already been used

The short answer

Bump versionCode and rebuild. Play has already seen the number you just uploaded, and version codes can never be reused — not after deletion, not after a rejected review, not on a different track.

In an Expo project, in app.json:

{
  "expo": {
    "android": {
      "versionCode": 6
    }
  }
}

Set it higher than anything you have ever uploaded — including to internal testing. If you are not sure what that is, Play Console → Release → App bundle explorer lists every version code it has ever accepted.

Note that versionCode is not version. The user-facing version string ("1.4.0") has no bearing on this error. Play only cares about the integer.

Why this happens

Version code is how Android decides what "newer" means. It is a plain integer, it must increase with every upload, and Play enforces uniqueness permanently so that a device can never be offered an update it has already had. That permanence is the part that surprises people: deleting a draft release, or having one rejected, does not release the number.

The three reasons it did not increment

  1. It is hardcoded and nobody moved it. The most common case. The value sits in app.json and only changes when a human edits it, so any build made without that edit reuses the last number.
  2. Two machines, two counters. If a teammate or a CI job uploaded a build you do not know about, your local idea of the last version code is behind. This is specifically why the App bundle explorer, not your git history, is the source of truth.
  3. Remote versioning is on and you edited the local value anyway. Some setups keep the counter server-side and increment it at build time. If that is enabled, the number in app.json is ignored, and editing it appears to do nothing at all. Decide which system owns the counter and let it own it.

Not hitting this again

Any scheme works as long as it is monotonic and there is exactly one of it. Two that hold up well:

  • Derive it from CI. A build number from your CI run is guaranteed monotonic and needs no coordination. It is the least clever option and it never fails.
  • Derive it from the date. Something like 20260821 makes the number self-describing and it will not collide unless you ship twice in a day.

What does not work is "everyone remembers to bump it." That is the system that produced this error.

Catching it before you build

Worth knowing where this one sits: a duplicate version code is only discoverable by asking Play, so nothing local can be certain about it before you upload. What a preflight can do is verify the submission path works at all — package name, service account, and release permission — so that when the upload does fail, the message you get is about the version code and not about three other things at once:

▸ Android
  ✓ Android identifier          com.kaya.app
  ✓ Upload keystore             alias upload — valid until 2051-12-11
  ✓ Play Developer API          can release to internal

Set up leas in 10 minutesFree, MIT licensed, and it never receives your signing keys.

If that didn’t fix it

  • You bumped it and the build still reports the old number. The value is baked in at build time. A rebuild is required — resubmitting the same artifact will not pick up an edited app.json.
  • Prebuild regenerated the native project. If a native build.gradle carries its own versionCode, it can win over app.json. Check the generated file rather than assuming.
  • The number is higher and Play still objects. Then the collision is on a different track or a closed testing release. App bundle explorer lists all of them.