App Store Connect build number: version vs build number
By Mehdi Azizi
Published , 8 min
The version is the number your customers see, the build number identifies each upload. The pair must be unique: with Expo, EAS bumps the build for you.
The App Store Connect build number is the CFBundleVersion key, and it identifies each upload. The version, CFBundleShortVersionString, is the number your customers see on the App Store. Apple requires the version and build number pair to be unique: a build number can only be used once for a given version.
With Expo, you set the version yourself and EAS can increment the build number on every production build. This guide explains both numbers, Apple's rules, the ITMS-90062 and ITMS-90189 errors, and what to check when your build doesn't show up.
I publish my iOS apps with Expo and EAS, including Solys, TradaZen and Nolera. The settings shown below come from their eas.json files.
Version vs build number: what's the difference?
Two Info.plist keys identify your app. Apple's documentation on CFBundleShortVersionString describes it as the user-visible version: three integers separated by periods, like 10.14.1. The one on CFBundleVersion covers the build version: one to three integers, with only digits and periods.
| Item | iOS key | Who sees it | Expo field |
|---|---|---|---|
| Version | CFBundleShortVersionString | Your customers | version |
| Build number | CFBundleVersion | You and Apple | ios.buildNumber |
Made-up example: for version 1.4.0, you upload builds 12, 13 and 14 while testing, then pick one for review. App Store Connect Help sums it up: the version ties the build to its listing, the build number identifies it everywhere in the system.
Apple's increment rules
- The pair must be unique. According to the Xcode Cloud documentation, App Store Connect requires a unique combination of version and build number. So an iPhone app can start back at 1 for a new version. A Mac app can't: its number must always go up.
- An approved version is closed. Once Apple has approved version 1.4.0, you can't add builds to it anymore. The next one needs a higher number.
- Each number is compared as an integer. 1.10 comes after 1.9, because 10 is greater than 9. A 1.9 version uploaded after an approved 1.20 will be rejected.
My advice: keep an integer build number that always goes up, and never reset it to 1. Resetting to 1 is allowed on iPhone, but a number that's unique across the app's whole life keeps you from mixing up two builds in TestFlight. That's what I see on my apps in remote mode: the counter keeps going from one version to the next.
Managing version and build with Expo and EAS
Expo's page on app versions, updated September 25, 2026, splits the roles. The version (version in app.json) stays yours: you change it when you prepare a new release. The build number (ios.buildNumber) can be handed off to EAS. Expo even lists forgetting to increment it as a common cause of rejected uploads.
Everything is set in eas.json:
{
"cli": {
"appVersionSource": "remote"
},
"build": {
"production": {
"autoIncrement": true
}
}
}
"remote": EAS servers keep the build number. This has been the recommended behavior since EAS CLI 12. The counter starts from the value in your config, or from 1, and after thatios.buildNumberis ignored."local": your config is the source of truth. WithautoIncrement, EAS editsios.buildNumberin your file, and you have to commit that change after every build.autoIncrement: the eas.json reference acceptstrueor"buildNumber"for the build, and"version"to bump the last digit of the version. In remote mode, Expo notes that"version"isn't supported.
On my side, TradaZen and Nolera use remote. Solys stayed on local: its build number lives in app.json and every production build bumps it in the file. Both work, but remote mode removes the risk of a forgotten commit.
Two commands round out the setup. eas build:version:set initializes the remote counter: enter the last number you uploaded to Apple. eas build:version:sync copies the remote values into your project, handy if you ever build with Xcode. With EAS Update, remote mode doesn't work with the nativeVersion policy: Expo recommends appVersion.
ITMS-90062: the version is already approved
The message looks like this (made-up numbers):
ERROR ITMS-90062: This bundle is invalid. The value for key
CFBundleShortVersionString [1.4.0] in the Info.plist file must
contain a higher version than that of the previously approved
version [1.4.0].
Apple has already approved version 1.4.0: you can't add builds to it anymore. Bump the version in app.json, for example to 1.4.1, then run a new build. Changing only the build number isn't enough.
If the error comes back even though version is up to date, look for an ios.version field. According to the Expo config reference, it overrides version on iOS. Same fix for its cousin ITMS-90186, "Invalid Pre-Release Train", which means a version is closed to new builds.
ITMS-90189: Redundant Binary Upload
This time, the build number is the problem:
ERROR ITMS-90189: Redundant Binary Upload. You've already uploaded
a build with build number '12' for version number '1.4.0'.
The 1.4.0 (12) pair already exists at Apple. With Expo, four causes come up again and again:
- The profile you used doesn't have
autoIncrement. If you create a separate profile for TestFlight, like Nolera's, add the option back there. - The remote counter is behind. You switched to
remoteafter manual uploads: runeas build:version:setwith the last number Apple knows. - You forgot the commit in local mode. The next build starts again from the old number.
- You're re-uploading the same binary. With
eas submit, pick the new build, not the old one.
The fix is always the same: a new build with a higher number.
"No builds available": your build doesn't show up
The build was uploaded, but your listing doesn't offer it. Check in this order.
- It's still processing. Apple processes every build before showing it and sends you an email when it's done. Expo usually mentions 10 to 15 minutes. According to Apple, after more than 24 hours in processing, you should open a Feedback Assistant ticket.
- It's waiting for your encryption declaration. That's the Missing Compliance status, covered below.
- The version doesn't match. A 1.4.1 build won't land under a listing prepared as 1.5.0 in App Store Connect. Align the two.
- A version was released in the meantime. According to the help page on choosing a build, the list then only shows builds uploaded since that release.
- It's the tester who can't see it. In the TestFlight app, "no builds available" often means the build isn't in any group, is waiting for beta review, or has expired. The details are in TestFlight to test your iPhone app.
Statuses to know
These are the statuses that most often explain a missing build, from Apple's list. Processing and Failed aren't on it: they're the upload statuses described in build tracking.
| Status | What it means | Your fix |
|---|---|---|
| Processing | Apple is processing it | Wait for the email |
| Failed | Processing error | Read the error, re-upload |
| Missing Compliance | Encryption not declared | Answer, or Info.plist |
| Invalid Binary | Non-compliant upload | Fix it, new build |
| Expired | Past 90 days | New build |
| Ready to Submit | Ready for testing or review | Add it to a group |
Declaring encryption once and for all
Without the ITSAppUsesNonExemptEncryption key, Apple asks you the compliance questions on every new version. With Expo, the field is called ios.config.usesNonExemptEncryption:
{
"expo": {
"ios": {
"config": {
"usesNonExemptEncryption": false
}
}
}
}
false means: no encryption, or only exempt encryption. Apple notes that encryption built into the operating system, like HTTPS connections, is generally exempt, and that your answer also covers your libraries. All three of my apps declare false. Only set false if it's true for your app: you're legally bound by the declaration.
Can you change the number of a build you already uploaded?
No. The number is baked into the signed binary: to fix it, you need a new build.
What you can change is the build attached to your version. Apple allows one build per version, but you can swap it as many times as you want until you submit for review:
- Open the version in App Store Connect, Build section.
- Hover over the current build and click the remove button, the minus sign.
- Click the add button, the plus sign, pick the right build, then save.
Removing a build from a version doesn't delete it from your account. If the version is already in review, remove the submission first: the review will start over from scratch.
Before your next upload
The build number is just one of the upload checks. The build image can trigger ITMS-90725, and signing has its own traps, covered in iOS developer certificate and provisioning profile. The full pipeline, from build to TestFlight, is in publishing an iOS app without a Mac, and review times are in App Store review time. Every step is gathered on the publish an app on the App Store page.
If you're preparing your first release, take the free diagnostic: it tells you what's blocking your project and sends you my Apple anti-rejection checklist. To build the app, wire up subscriptions and publish it, the iOS & Android Kit walks you through the four-step path with the starter code from my apps, at your own pace.
Frequently asked questions
What's the difference between version and build number in App Store Connect?
The version is your release's public number, like 1.4.0. The build number identifies a specific binary uploaded to Apple for that version. You can upload several builds for the same version, each with its own number.
Do I need to change the build number on every upload?
Yes, for the same version. Apple rejects a second upload with the same version and build number pair: that's the ITMS-90189 error. With EAS, autoIncrement handles it on every production build.
Should the build number reset to 1 for each version?
It's not required. On iPhone, Apple accepts a lower number for a new version, since only the pair has to be unique. A counter that always goes up is still easier to track.
How do I change the build number in App Store Connect?
You can't edit the number of a build you already uploaded. You can, however, replace the build attached to your version from the listing's Build section, as long as it isn't in review. For a new number, make a new build.
Why isn't my build showing up in App Store Connect?
Most of the time, it's still processing or waiting for your encryption declaration. Also check that its version matches your listing's. After more than 24 hours in processing, Apple asks you to open a ticket.

