# Build number в App Store Connect: версія і номер збірки

> Версію бачать твої клієнти, а build number ідентифікує кожне завантаження. Пара має бути унікальною: з Expo номер збірки збільшує EAS.

Оригінальна сторінка: [Build number в App Store Connect: версія і номер збірки](https://devoria.fr/uk/blog/app-store-connect-build-number-version)
Автор: [Mehdi Azizi](https://devoria.fr/uk/mehdi-azizi)
Опубліковано: 2026-11-04
Останнє оновлення змісту: 2026-11-04


Build number в App Store Connect означає номер збірки: ключ `CFBundleVersion`, який ідентифікує кожне завантаження. Версія, `CFBundleShortVersionString`, це номер, який твої клієнти бачать в App Store. **Apple вимагає, щоб пара «версія і номер збірки» була унікальною: номер збірки використовується лише один раз для однієї версії.**

З Expo версію ти задаєш сам, а EAS може збільшувати номер збірки при кожній production-збірці. У цьому гайді я пояснюю обидва номери, правила Apple, помилки ITMS-90062 та ITMS-90189 і що перевірити, коли твоя збірка не з'являється.

Я публікую свої iOS-застосунки з Expo та EAS, серед них Solys, TradaZen і Nolera. Налаштування нижче взяті з їхніх файлів `eas.json`.

## Версія і номер збірки: у чому різниця?

Твій застосунок ідентифікують два ключі Info.plist. [Документація Apple про CFBundleShortVersionString](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleshortversionstring) описує його як версію, яку бачить користувач: три цілі числа через крапку, наприклад 10.14.1. [Документація про CFBundleVersion](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleversion) говорить про версію збірки: від одного до трьох цілих чисел, лише цифри та крапки.

| Елемент      | Ключ iOS                   | Хто її бачить | Поле Expo         |
| ------------ | -------------------------- | ------------- | ----------------- |
| Версія       | CFBundleShortVersionString | Твої клієнти  | `version`         |
| Номер збірки | CFBundleVersion            | Ти та Apple   | `ios.buildNumber` |

Вигаданий приклад: для версії 1.4.0 ти під час тестів завантажуєш збірки 12, 13 і 14, а потім вибираєш одну з них для рев'ю. [Довідка App Store Connect](https://developer.apple.com/help/app-store-connect/manage-builds/upload-builds) підсумовує це так: версія прив'язує збірку до її сторінки, а номер збірки ідентифікує її всюди в системі.

## Правила збільшення номерів від Apple

1. **Пара має бути унікальною.** Згідно з [документацією Xcode Cloud](https://developer.apple.com/documentation/xcode/setting-the-next-build-number-for-xcode-cloud-builds), App Store Connect вимагає унікальної комбінації версії та номера збірки. Тож застосунок для iPhone може почати знову з 1 для нової версії. Застосунок для Mac не може: його номер має завжди зростати.
2. **Схвалена версія закрита.** Щойно Apple схвалила версію 1.4.0, додати до неї збірку вже не вийде. Наступна має мати вищий номер.
3. **Кожне число порівнюється як ціле.** 1.10 іде після 1.9, бо 10 більше за 9. Версію 1.9, завантажену після схваленої 1.20, буде відхилено.

Моя порада: **тримай цілий номер збірки, який завжди зростає, і не скидай його до 1.** Почати знову з 1 на iPhone можна, але унікальний номер на все життя застосунку не дає сплутати дві збірки в TestFlight. Саме так це виглядає в моїх застосунках у віддаленому режимі: лічильник продовжується від версії до версії.

## Як керувати версією і збіркою з Expo та EAS

[Сторінка Expo про версії](https://docs.expo.dev/build-reference/app-versions/), оновлена 25 вересня 2026 року, розділяє ролі. Версія (`version` в app.json) залишається за тобою: ти змінюєш її, коли готуєш новий реліз. Номер збірки (`ios.buildNumber`) можна доручити EAS. До речі, Expo називає забутий інкремент частою причиною відмови під час завантаження.

Усе налаштовується в eas.json:

```json
{
  "cli": {
    "appVersionSource": "remote"
  },
  "build": {
    "production": {
      "autoIncrement": true
    }
  }
}
```

- **`"remote"`**: номер збірки зберігають сервери EAS. Це рекомендована поведінка, починаючи з EAS CLI 12. Лічильник стартує зі значення у твоїй конфігурації або з 1, а далі `ios.buildNumber` ігнорується.
- **`"local"`**: головною є твоя конфігурація. З `autoIncrement` EAS змінює `ios.buildNumber` у твоєму файлі, і цю зміну треба комітити після кожної збірки.
- **`autoIncrement`**: [довідник eas.json](https://docs.expo.dev/eas/json/) приймає `true` або `"buildNumber"` для збірки та `"version"`, щоб збільшити останню цифру версії. Expo уточнює, що у віддаленому режимі `"version"` не підтримується.

У мене TradaZen і Nolera працюють у режимі `remote`. Solys лишилася в `local`: її номер збірки живе в app.json, і кожна production-збірка збільшує його у файлі. **Обидва варіанти працюють, але віддалений режим прибирає ризик забутого коміту.**

Систему доповнюють дві команди. `eas build:version:set` ініціалізує віддалений лічильник: введи останній номер, надісланий в Apple. `eas build:version:sync` копіює віддалені значення у твій проєкт, це корисно, якщо колись збиратимеш через Xcode. З EAS Update віддалений режим не працює з політикою `nativeVersion`: Expo радить `appVersion`.

## ITMS-90062: версію вже схвалено

Повідомлення виглядає так (номери вигадані):

```text
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 уже схвалила версію 1.4.0: додати до неї збірку більше не можна. **Підніми версію в app.json, наприклад до 1.4.1, і запусти збірку знову.** Змінити лише номер збірки недостатньо.

Якщо помилка повертається, хоча `version` оновлено, пошукай поле `ios.version`. Згідно з [довідником конфігурації Expo](https://docs.expo.dev/versions/latest/config/app/), воно має пріоритет над `version` для iOS. Те саме рішення для спорідненої помилки ITMS-90186, «Invalid Pre-Release Train», яка сигналізує, що версія закрита для нових збірок.

## ITMS-90189: Redundant Binary Upload

Тут проблема в номері збірки:

```text
ERROR ITMS-90189: Redundant Binary Upload. You've already uploaded
a build with build number '12' for version number '1.4.0'.
```

Пара 1.4.0 (12) уже існує в Apple. З Expo найчастіше трапляються чотири причини:

- **У використаному профілі немає `autoIncrement`.** Якщо ти створюєш окремий профіль для TestFlight, як у Nolera, додай туди цю опцію.
- **Віддалений лічильник відстає.** Ти перейшов на `remote` після ручних завантажень: запусти `eas build:version:set` з останнім номером, відомим Apple.
- **У локальному режимі забули коміт.** Наступна збірка стартує зі старого номера.
- **Ти надсилаєш той самий бінарник.** В `eas submit` вибирай нову збірку, а не стару.

**Виправлення завжди однакове: нова збірка з вищим номером.**

## «No builds available»: твоя збірка не з'являється

Збірку відправлено, але твоя сторінка її не пропонує. Перевір у такому порядку.

1. **Вона ще обробляється.** Apple обробляє кожну збірку, перш ніж її показати, і надсилає тобі e-mail після завершення. [Expo](https://docs.expo.dev/submit/ios/) зазвичай говорить про 10-15 хвилин. [За словами Apple](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata), якщо обробка триває понад 24 години, треба відкрити тікет у Feedback Assistant.
2. **Вона чекає на твою декларацію про шифрування.** Це статус Missing Compliance, детальніше нижче.
3. **Версія не збігається.** Збірка 1.4.1 не потрапить на сторінку, підготовлену як 1.5.0 в App Store Connect. Вирівняй їх.
4. **Тим часом вийшла версія.** Згідно з [довідкою про вибір збірки](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit), тоді список показує лише збірки, завантажені після цього релізу.
5. **Її не бачить тестувальник.** У застосунку TestFlight «no builds available» часто означає, що збірка не входить у жодну групу, чекає на бета-рев'ю або закінчився її термін. Подробиці в статті [TestFlight для тестування твого застосунку для iPhone](https://devoria.fr/uk/blog/testflight-testuvannya-zastosunku-iphone).

### Статуси, які варто знати

Статуси, які найчастіше пояснюють відсутність збірки, згідно з [переліком Apple](https://developer.apple.com/help/app-store-connect/reference/app-build-statuses). Processing і Failed у ньому немає: це статуси завантаження, описані в [розділі про відстеження збірок](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata).

| Статус             | Що він означає              | Як виправити                       |
| ------------------ | --------------------------- | ---------------------------------- |
| Processing         | Apple обробляє збірку       | Чекати на e-mail                   |
| Failed             | Помилка під час обробки     | Прочитати помилку, надіслати знову |
| Missing Compliance | Шифрування не задекларовано | Відповісти або Info.plist          |
| Invalid Binary     | Невідповідне завантаження   | Виправити, нова збірка             |
| Expired            | Минуло 90 днів              | Нова збірка                        |
| Ready to Submit    | Готова до тесту чи рев'ю    | Додати її до групи                 |

### Задекларуй шифрування раз і назавжди

Без ключа `ITSAppUsesNonExemptEncryption` [Apple](https://developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption) ставить тобі питання про відповідність при кожній новій версії. В Expo це поле називається `ios.config.usesNonExemptEncryption`:

```json
{
  "expo": {
    "ios": {
      "config": {
        "usesNonExemptEncryption": false
      }
    }
  }
}
```

`false` означає: шифрування немає або є лише звільнене від вимог шифрування. [Apple уточнює](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations), що вбудоване в систему шифрування, як-от HTTPS-з'єднання, зазвичай звільнене, і що відповідь стосується також твоїх бібліотек. Усі три мої застосунки декларують `false`. **Став `false`, лише якщо це правда для твого застосунку: ти несеш відповідальність за цю декларацію.**

## Чи можна змінити номер уже завантаженої збірки?

Ні. Номер записаний у підписаний бінарник: щоб його виправити, потрібна нова збірка.

Змінити можна збірку, прив'язану до твоєї версії. Apple дозволяє лише одну збірку на версію, але [ти можеш замінювати її скільки завгодно разів](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit) до відправлення на рев'ю:

1. Відкрий версію в App Store Connect, розділ Build.
2. Наведи курсор на поточну збірку й натисни кнопку видалення, знак мінус.
3. Натисни кнопку додавання, знак плюс, вибери потрібну збірку і збережи.

Відкріплення збірки від версії не видаляє її з твого акаунта. Якщо версія вже на рев'ю, [спочатку відклич заявку](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/remove-a-submission-from-review): рев'ю почнеться з нуля.

## Перед наступним завантаженням

Номер збірки лише одна з перевірок під час завантаження. Образ збірки може спричинити [ITMS-90725](https://devoria.fr/uk/blog/itms-90725-sdk-version-issue-expo), а підпис має власні пастки, описані в статті [сертифікат розробника iOS і provisioning profile](https://devoria.fr/uk/blog/ios-developer-certificate-provisioning-profile-expo). Увесь ланцюжок, від збірки до TestFlight, є в статті [як опублікувати iOS-застосунок без Mac](https://devoria.fr/uk/blog/publish-ios-app-without-mac-expo-eas), а терміни рев'ю в статті [скільки триває перевірка в App Store](https://devoria.fr/uk/blog/skilky-tryvaie-perevirka-app-store-app-review). Усі кроки зібрано на сторінці [як опублікувати застосунок в App Store](https://devoria.fr/uk/expertise/publish-an-app-on-the-app-store).

Якщо готуєш свій перший реліз, [пройди безкоштовну діагностику](https://devoria.fr/uk/diagnostic): вона покаже, що блокує твій проєкт, і надішле тобі мій чекліст проти відмов Apple. Щоб створити застосунок, підключити підписки й опублікувати його, [iOS & Android Kit](https://devoria.fr/uk/kits/ios) веде тебе маршрутом із чотирьох етапів зі стартовим кодом моїх застосунків, у твоєму темпі.

## Поширені запитання

### Яка різниця між версією і build number в App Store Connect?

Версія це публічний номер твого релізу, наприклад 1.4.0. Build number ідентифікує конкретний бінарник, надісланий в Apple для цієї версії. Для однієї версії можна надіслати кілька збірок, кожну зі своїм номером.

### Чи треба змінювати номер збірки при кожному завантаженні?

Так, у межах однієї версії. Apple відхиляє друге завантаження з тією самою парою версії та номера збірки, це помилка ITMS-90189. З EAS цим займається `autoIncrement` при кожній production-збірці.

### Чи має номер збірки починатися з 1 для кожної версії?

Це не обов'язково. На iPhone Apple приймає нижчий номер для нової версії, бо унікальною має бути лише пара. Лічильник, який завжди зростає, простіше відстежувати.

### Як змінити build number в App Store Connect?

Змінити номер уже завантаженої збірки не можна. Натомість можна замінити збірку, прив'язану до твоєї версії, у розділі Build сторінки, поки вона не на рев'ю. Для нового номера зроби нову збірку.

### Чому моя збірка не з'являється в App Store Connect?

Найчастіше вона ще обробляється або чекає на твою декларацію про шифрування. Перевір також, чи її версія збігається з версією на сторінці. Якщо обробка триває понад 24 години, Apple просить відкрити тікет.


## Твій проєкт

[Review Kit](https://devoria.fr/uk/kits/app-review): Мій чекліст для перевірки в App Store, виправлені відмови Apple, чекліст для Google Play і три скіли для Claude Code. 2 499 ₴.

[iOS & Android Kit](https://devoria.fr/uk/kits/ios): Створи свій застосунок для iPhone і Android з Claude Code: стартовий код моїх застосунків, шлях до публікації в сторах і всі кіти. 4 999 ₴.

[Діагностика: що відділяє тебе від твого застосунку для iPhone](https://devoria.fr/uk/diagnostic): 7 запитань, 60 секунд: ти дізнаєшся, що насправді заважає тобі опублікувати застосунок для iPhone, отримаєш свій шлях у 4 кроки і кіт, який тобі підходить.
