altool ERROR ITMS-90189 redundant binary upload in CI
App Store Connect rejected the upload with ITMS-90189 because a binary already exists for that version and build number. Unlike a plain version collision, this fires when the exact train and build pair has already been accepted, so the new upload is redundant.
What this error means
altool --upload-app fails with "ERROR ITMS-90189: Redundant Binary Upload. There already exists a binary upload with build version X for train version Y". The job succeeded earlier but a retry re-sent the same build.
ERROR ITMS-90189: "Redundant Binary Upload. There already exists a binary upload with
build version '12' for train version '1.4.0'. You must increment the build version
before you upload another binary."Common causes
A retried job re-uploaded an accepted build
The first upload already succeeded; a CI retry re-ran the upload step with the same CFBundleVersion, which App Store Connect treats as redundant.
The build number was never bumped between uploads
Two pipeline runs produced the same train and build pair because the build number is static.
How to fix it
Increment the build version before re-uploading
- Treat ITMS-90189 as a success-with-duplicate: the prior upload exists in App Store Connect.
- If you genuinely need a new binary, bump CFBundleVersion.
- Re-archive and upload only when the build number is new.
agvtool new-version -all "$((PREV_BUILD + 1))"Make the upload step idempotent
Query the latest TestFlight build first and skip the upload if the current build number already exists, so retries do not fail the job.
latest=$(fastlane run latest_testflight_build_number app_identifier:com.example.app)
# only upload when your local build number is greater than $latestHow to prevent it
- Bump the build number on every produced archive.
- Guard the upload step so a retry does not resend an accepted build.
- Source build numbers from a unique CI counter.