# Build number w App Store Connect: wersja i numer buildu

> Wersję widzą twoi klienci, a build number identyfikuje każdy upload. Para musi być unikalna, a z Expo numer buildu podbija za ciebie EAS.

Oryginalna strona: [Build number w App Store Connect: wersja i numer buildu](https://devoria.fr/pl/blog/app-store-connect-build-number-wersja)
Autor: [Mehdi Azizi](https://devoria.fr/pl/mehdi-azizi)
Publikacja: 2026-11-04
Ostatnia aktualizacja treści: 2026-11-04


Build number w App Store Connect to numer buildu, czyli klucz `CFBundleVersion`, który identyfikuje każdy upload. Wersja, `CFBundleShortVersionString`, to numer, który twoi klienci widzą w App Store. **Apple wymaga, żeby para wersja i numer buildu była unikalna: danego numeru buildu używasz tylko raz w obrębie jednej wersji.**

Z Expo wersję ustawiasz sam, a EAS może podbijać numer buildu przy każdym buildzie produkcyjnym. W tym poradniku wyjaśniam oba numery, zasady Apple, błędy ITMS-90062 i ITMS-90189 oraz to, co sprawdzić, gdy twój build się nie pojawia.

Swoje aplikacje iOS publikuję z Expo i EAS, w tym Solys, TradaZen i Nolera. Ustawienia pokazane niżej pochodzą z ich plików `eas.json`.

## Wersja a numer buildu: jaka jest różnica?

Twoją aplikację identyfikują dwa klucze w Info.plist. [Dokumentacja Apple o CFBundleShortVersionString](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleshortversionstring) opisuje go jako wersję widoczną dla użytkownika: trzy liczby całkowite oddzielone kropkami, np. 10.14.1. [Ta o CFBundleVersion](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleversion) mówi o wersji buildu: od jednej do trzech liczb całkowitych, tylko cyfry i kropki.

| Element      | Klucz iOS                  | Kto go widzi | Pole w Expo       |
| ------------ | -------------------------- | ------------ | ----------------- |
| Wersja       | CFBundleShortVersionString | Twoi klienci | `version`         |
| Numer buildu | CFBundleVersion            | Ty i Apple   | `ios.buildNumber` |

Fikcyjny przykład: dla wersji 1.4.0 w trakcie testów wysyłasz buildy 12, 13 i 14, a potem wybierasz jeden do recenzji. [Pomoc App Store Connect](https://developer.apple.com/help/app-store-connect/manage-builds/upload-builds) podsumowuje to tak: wersja łączy build z jego kartą, a numer buildu identyfikuje go w całym systemie.

## Zasady podbijania numerów w Apple

1. **Para musi być unikalna.** Według [dokumentacji Xcode Cloud](https://developer.apple.com/documentation/xcode/setting-the-next-build-number-for-xcode-cloud-builds) App Store Connect wymaga unikalnej kombinacji wersji i numeru buildu. Aplikacja na iPhone'a może więc zacząć od 1 przy nowej wersji. Aplikacja na Maca nie: jej numer musi zawsze rosnąć.
2. **Zatwierdzona wersja jest zamknięta.** Gdy Apple zatwierdzi wersję 1.4.0, nie dodasz do niej już żadnego buildu. Kolejna musi mieć wyższy numer.
3. **Każda liczba jest porównywana jako liczba całkowita.** 1.10 jest po 1.9, bo 10 jest większe od 9. Wersja 1.9 wysłana po zatwierdzonej 1.20 zostanie odrzucona.

Moja rada: **trzymaj całkowity numer buildu, który zawsze rośnie, i nie resetuj go do 1.** Na iPhonie reset jest dozwolony, ale numer unikalny przez całe życie aplikacji chroni przed pomyleniem dwóch buildów w TestFlight. Tak to wygląda w moich aplikacjach w trybie zdalnym: licznik leci dalej z wersji na wersję.

## Wersja i build w Expo i EAS

[Strona Expo o wersjach](https://docs.expo.dev/build-reference/app-versions/), zaktualizowana 25 września 2026, rozdziela role. Wersja (`version` w app.json) należy do ciebie: zmieniasz ją, gdy szykujesz nowe wydanie. Numer buildu (`ios.buildNumber`) możesz powierzyć EAS. Expo zresztą wymienia zapomnienie o jego podbiciu jako częstą przyczynę odrzucenia przy uploadzie.

Wszystko ustawiasz w eas.json:

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

- **`"remote"`**: numer buildu przechowują serwery EAS. To zalecane zachowanie od EAS CLI 12. Licznik startuje od wartości z twojej konfiguracji albo od 1, a potem `ios.buildNumber` jest ignorowany.
- **`"local"`**: rozstrzyga twoja konfiguracja. Z `autoIncrement` EAS zmienia `ios.buildNumber` w twoim pliku i przy każdym buildzie musisz tę zmianę zacommitować.
- **`autoIncrement`**: [dokumentacja eas.json](https://docs.expo.dev/eas/json/) przyjmuje `true` albo `"buildNumber"` dla buildu oraz `"version"`, żeby podbić ostatnią cyfrę wersji. Expo zaznacza, że w trybie zdalnym `"version"` nie jest obsługiwane.

U mnie TradaZen i Nolera działają w `remote`. Solys została w `local`: jej numer buildu siedzi w app.json i każdy build produkcyjny podbija go w pliku. **Oba sposoby działają, ale tryb zdalny eliminuje ryzyko zapomnianego commita.**

Całość uzupełniają dwie komendy. `eas build:version:set` inicjalizuje zdalny licznik: wpisz ostatni numer wysłany do Apple. `eas build:version:sync` kopiuje zdalne wartości do projektu, co się przydaje, jeśli kiedyś zbudujesz aplikację w Xcode. Przy EAS Update tryb zdalny nie działa z polityką `nativeVersion`: Expo radzi `appVersion`.

## ITMS-90062: wersja jest już zatwierdzona

Komunikat wygląda tak (numery fikcyjne):

```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 już zatwierdziło wersję 1.4.0: nie dodasz do niej kolejnego buildu. **Podbij wersję w app.json, np. do 1.4.1, i odpal build jeszcze raz.** Sama zmiana numeru buildu nie wystarczy.

Jeśli błąd wraca, choć `version` jest aktualne, poszukaj pola `ios.version`. Według [dokumentacji konfiguracji Expo](https://docs.expo.dev/versions/latest/config/app/) ma ono pierwszeństwo przed `version` na iOS. To samo lekarstwo działa na pokrewny błąd ITMS-90186, „Invalid Pre-Release Train”, który oznacza wersję zamkniętą dla nowych buildów.

## ITMS-90189: Redundant Binary Upload

Tutaj problemem jest numer buildu:

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

Para 1.4.0 (12) już istnieje u Apple. Z Expo powtarzają się cztery przyczyny:

- **Użyty profil nie ma `autoIncrement`.** Jeśli tworzysz osobny profil pod TestFlight, jak ten w Nolera, dodaj tam tę opcję.
- **Zdalny licznik jest w tyle.** Przeszedłeś na `remote` po ręcznych uploadach: uruchom `eas build:version:set` z ostatnim numerem znanym Apple.
- **W trybie lokalnym zapomniałeś o commicie.** Następny build startuje od starego numeru.
- **Wysyłasz ten sam plik binarny.** W `eas submit` wybierz nowy build, nie stary.

**Poprawka jest zawsze ta sama: nowy build z wyższym numerem.**

## „No builds available”: twój build się nie pojawia

Build poszedł, ale twoja karta go nie proponuje. Sprawdź w tej kolejności.

1. **Wciąż jest przetwarzany.** Apple przetwarza każdy build, zanim go pokaże, i na koniec wysyła ci e-mail. [Expo](https://docs.expo.dev/submit/ios/) mówi zwykle o 10 do 15 minutach. [Według Apple](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata) po ponad 24 godzinach przetwarzania trzeba otworzyć zgłoszenie w Feedback Assistant.
2. **Czeka na twoją deklarację szyfrowania.** To status Missing Compliance, opisany niżej.
3. **Wersja się nie zgadza.** Build 1.4.1 nie trafi pod kartę przygotowaną jako 1.5.0 w App Store Connect. Wyrównaj obie.
4. **W międzyczasie wyszła jakaś wersja.** Według [pomocy o wyborze buildu](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit) lista pokazuje wtedy tylko buildy wysłane od tego wydania.
5. **To tester go nie widzi.** W aplikacji TestFlight „no builds available” często oznacza, że build nie jest w żadnej grupie, czeka na recenzję beta albo wygasł. Szczegóły znajdziesz w [TestFlight do testowania aplikacji na iPhone'a](https://devoria.fr/pl/blog/testflight-testowanie-aplikacji-iphone).

### Statusy, które warto znać

Statusy, które najczęściej tłumaczą brak buildu, według [listy Apple](https://developer.apple.com/help/app-store-connect/reference/app-build-statuses). Processing i Failed na niej nie ma: to statusy uploadu opisane w [śledzeniu buildów](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata).

| Status             | Co oznacza                    | Twoja poprawka                   |
| ------------------ | ----------------------------- | -------------------------------- |
| Processing         | Apple przetwarza build        | Poczekaj na e-mail               |
| Failed             | Błąd przetwarzania            | Przeczytaj błąd, wyślij ponownie |
| Missing Compliance | Szyfrowanie niezadeklarowane  | Odpowiedz lub Info.plist         |
| Invalid Binary     | Niezgodny upload              | Popraw, nowy build               |
| Expired            | Minęło 90 dni                 | Nowy build                       |
| Ready to Submit    | Gotowy do testów lub recenzji | Dodaj go do grupy                |

### Zadeklaruj szyfrowanie raz na zawsze

Bez klucza `ITSAppUsesNonExemptEncryption` [Apple](https://developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption) zadaje ci pytania o zgodność przy każdej nowej wersji. W Expo pole nazywa się `ios.config.usesNonExemptEncryption`:

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

`false` oznacza: brak szyfrowania albo tylko szyfrowanie zwolnione. [Apple wyjaśnia](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations), że szyfrowanie wbudowane w system, np. połączenia HTTPS, jest zwykle zwolnione, a odpowiedź obejmuje też twoje biblioteki. Moje trzy aplikacje deklarują `false`. **Ustaw `false` tylko wtedy, gdy to prawda dla twojej aplikacji: ta deklaracja cię zobowiązuje.**

## Czy można zmienić numer już wysłanego buildu?

Nie. Numer jest zapisany w podpisanym pliku binarnym: żeby go poprawić, potrzebujesz nowego buildu.

Zmienić możesz za to build przypięty do wersji. Apple pozwala na jeden build na wersję, ale [możesz go podmieniać, ile chcesz](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit), aż do wysłania do recenzji:

1. Otwórz wersję w App Store Connect, sekcja Build.
2. Najedź na obecny build i kliknij przycisk usuwania, czyli znak minus.
3. Kliknij przycisk dodawania, czyli znak plus, wybierz właściwy build i zapisz.

Odpięcie buildu od wersji nie usuwa go z twojego konta. Jeśli wersja jest już w recenzji, [najpierw wycofaj zgłoszenie](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/remove-a-submission-from-review): recenzja zacznie się od zera.

## Przed następnym uploadem

Numer buildu to tylko jedna z kontroli przy uploadzie. Obraz buildu może wywołać [ITMS-90725](https://devoria.fr/pl/blog/itms-90725-sdk-version-issue-expo), a podpisywanie ma własne pułapki, opisane w [certyfikat dewelopera iOS i provisioning profile](https://devoria.fr/pl/blog/certyfikat-dewelopera-ios-provisioning-profile-expo). Cały proces, od buildu do TestFlight, znajdziesz w [publikacja aplikacji iOS bez Maca](https://devoria.fr/pl/blog/publikacja-aplikacji-ios-bez-maca-expo-eas), a czasy recenzji w [czas weryfikacji w App Store](https://devoria.fr/pl/blog/czas-weryfikacji-app-store-ile-czekac). Wszystkie kroki zebrałem na stronie [publikacja aplikacji w App Store](https://devoria.fr/pl/expertise/publikacja-aplikacji-w-app-store).

Jeśli szykujesz swoje pierwsze wydanie, [zrób darmową diagnozę](https://devoria.fr/pl/diagnostic): powie ci, co blokuje twój projekt, i wyśle ci moją checklistę przeciw odrzuceniom przez Apple. Żeby zbudować aplikację, podpiąć subskrypcje i ją opublikować, [iOS & Android Kit](https://devoria.fr/pl/kits/ios) prowadzi cię przez cztery etapy z kodem startowym moich aplikacji, we własnym tempie.

## Najczęściej zadawane pytania

### Jaka jest różnica między wersją a build number w App Store Connect?

Wersja to publiczny numer twojego wydania, np. 1.4.0. Build number identyfikuje konkretny plik binarny wysłany do Apple dla tej wersji. Dla jednej wersji możesz wysłać kilka buildów, każdy z własnym numerem.

### Czy trzeba zmieniać numer buildu przy każdym uploadzie?

Tak, w obrębie jednej wersji. Apple odrzuca drugi upload z tą samą parą wersji i numeru buildu, to błąd ITMS-90189. Z EAS zajmuje się tym `autoIncrement` przy każdym buildzie produkcyjnym.

### Czy numer buildu musi wracać do 1 przy każdej wersji?

Nie jest to obowiązkowe. Na iPhonie Apple akceptuje niższy numer dla nowej wersji, bo unikalna musi być tylko para. Licznik, który zawsze rośnie, łatwiej jednak śledzić.

### Jak zmienić build number w App Store Connect?

Nie zmienisz numeru już wysłanego buildu. Możesz za to podmienić build przypięty do wersji w sekcji Build karty, dopóki nie jest w recenzji. Żeby mieć nowy numer, zrób nowy build.

### Dlaczego mój build nie pojawia się w App Store Connect?

Najczęściej wciąż jest przetwarzany albo czeka na twoją deklarację szyfrowania. Sprawdź też, czy jego wersja zgadza się z wersją na karcie. Po ponad 24 godzinach przetwarzania Apple prosi o otwarcie zgłoszenia.


## Twój projekt

[Review Kit](https://devoria.fr/pl/kits/app-review): Moja checklista do App Store Review, poprawione odrzucenia od Apple, checklista do Google Play i trzy skille Claude Code. 219 zł.

[iOS & Android Kit](https://devoria.fr/pl/kits/ios): Stwórz swoją aplikację na iPhone'a i Androida z Claude Code: kod startowy moich aplikacji, droga aż do sklepów i wszystkie kity. 439 zł.

[Diagnoza: co dzieli cię od twojej aplikacji na iPhone'a](https://devoria.fr/pl/diagnostic): 7 pytań, 60 sekund: wiesz, co naprawdę blokuje publikację twojej aplikacji na iPhone'a, masz plan w 4 krokach i kit dopasowany do ciebie.
