# App Store Connect build number : version et numéro de build

> La version est le numéro que voient tes clients, le build number identifie chaque envoi. Le couple doit être unique : avec Expo, EAS monte le build pour toi.

Page originale : [App Store Connect build number : version et numéro de build](https://devoria.fr/blog/numero-de-build-version-app-store-connect)
Auteur : [Mehdi Azizi](https://devoria.fr/mehdi-azizi)
Publication : 2026-11-04
Dernière révision du contenu : 2026-11-04


Le build number d'App Store Connect, c'est le numéro de build : la clé `CFBundleVersion`, qui identifie chaque envoi. La version, `CFBundleShortVersionString`, est le numéro que tes clients voient sur l'App Store. **Apple exige que le couple version et numéro de build soit unique : un numéro de build ne sert qu'une fois pour une même version.**

Avec Expo, tu fixes la version toi-même et EAS peut incrémenter le numéro de build à chaque build de production. Ce guide explique les deux numéros, les règles d'Apple, les erreurs ITMS-90062 et ITMS-90189, et quoi vérifier quand ton build n'apparaît pas.

Je publie mes apps iOS avec Expo et EAS, dont Solys, TradaZen et Nolera. Les réglages montrés plus bas sont ceux de leurs fichiers `eas.json`.

## Version et numéro de build : quelle différence ?

Deux clés de l'Info.plist identifient ton app. [La documentation d'Apple sur CFBundleShortVersionString](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleshortversionstring) la décrit comme la version visible par l'utilisateur : trois entiers séparés par des points, comme 10.14.1. [Celle sur CFBundleVersion](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundleversion) parle de la version du build : un à trois entiers, avec seulement des chiffres et des points.

| Élément         | Clé iOS                    | Qui la voit  | Champ Expo        |
| --------------- | -------------------------- | ------------ | ----------------- |
| Version         | CFBundleShortVersionString | Tes clients  | `version`         |
| Numéro de build | CFBundleVersion            | Toi et Apple | `ios.buildNumber` |

Exemple fictif : pour la version 1.4.0, tu envoies les builds 12, 13 et 14 pendant tes tests, puis tu en choisis un pour la revue. [L'aide d'App Store Connect](https://developer.apple.com/help/app-store-connect/manage-builds/upload-builds) le résume : la version rattache le build à sa fiche, le numéro de build l'identifie partout dans le système.

## Les règles d'incrément d'Apple

1. **Le couple doit être unique.** D'après [la documentation de Xcode Cloud](https://developer.apple.com/documentation/xcode/setting-the-next-build-number-for-xcode-cloud-builds), App Store Connect exige une combinaison unique de version et de numéro de build. Une app iPhone peut donc repartir à 1 pour une nouvelle version. Une app Mac, non : son numéro doit toujours monter.
2. **Une version approuvée est fermée.** Une fois qu'Apple a validé la version 1.4.0, tu ne peux plus lui ajouter de build. La suivante doit porter un numéro plus haut.
3. **Chaque nombre se compare comme un entier.** 1.10 passe après 1.9, parce que 10 est plus grand que 9. Une version 1.9 envoyée après une 1.20 approuvée sera refusée.

Mon conseil : **garde un numéro de build entier qui monte toujours, sans le remettre à 1.** Repartir à 1 est permis sur iPhone, mais un numéro unique sur toute la vie de l'app évite de confondre deux builds dans TestFlight. C'est ce que je vois sur mes apps en mode distant : le compteur continue d'une version à l'autre.

## Gérer version et build avec Expo et EAS

[La page d'Expo sur les versions](https://docs.expo.dev/build-reference/app-versions/), mise à jour le 25 septembre 2026, sépare les rôles. La version (`version` dans app.json) reste à toi : tu la changes quand tu prépares une nouvelle sortie. Le numéro de build (`ios.buildNumber`) peut être confié à EAS. Expo cite d'ailleurs l'oubli de l'incrémenter comme une cause courante de refus à l'envoi.

Tout se règle dans eas.json :

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

- **`"remote"`** : les serveurs d'EAS gardent le numéro de build. C'est le comportement recommandé depuis EAS CLI 12. Le compteur part de la valeur de ta configuration, ou de 1, puis `ios.buildNumber` est ignoré.
- **`"local"`** : ta configuration fait foi. Avec `autoIncrement`, EAS modifie `ios.buildNumber` dans ton fichier, et tu dois committer ce changement à chaque build.
- **`autoIncrement`** : [la référence d'eas.json](https://docs.expo.dev/eas/json/) accepte `true` ou `"buildNumber"` pour le build, et `"version"` pour monter le dernier chiffre de la version. En mode distant, Expo précise que `"version"` n'est pas pris en charge.

Chez moi, TradaZen et Nolera sont en `remote`. Solys est restée en `local` : son numéro de build vit dans app.json et chaque build de production le fait monter dans le fichier. **Les deux marchent, mais le mode distant supprime le risque d'un commit oublié.**

Deux commandes complètent le dispositif. `eas build:version:set` initialise le compteur distant : saisis le dernier numéro envoyé à Apple. `eas build:version:sync` recopie les valeurs distantes dans ton projet, utile si tu compiles un jour avec Xcode. Avec EAS Update, le mode distant ne marche pas avec la politique `nativeVersion` : Expo conseille `appVersion`.

## ITMS-90062 : la version est déjà approuvée

Le message ressemble à ceci (numéros fictifs) :

```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 a déjà approuvé la version 1.4.0 : tu ne peux plus y ajouter de build. **Monte la version dans app.json, par exemple en 1.4.1, puis relance un build.** Changer seulement le numéro de build ne suffit pas.

Si l'erreur revient alors que `version` est à jour, cherche un champ `ios.version`. D'après [la référence de la configuration Expo](https://docs.expo.dev/versions/latest/config/app/), il prend le pas sur `version` pour iOS. Même remède pour l'erreur cousine ITMS-90186, « Invalid Pre-Release Train », qui signale une version fermée aux nouveaux builds.

## ITMS-90189 : Redundant Binary Upload

Ici, c'est le numéro de build qui coince :

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

Le couple 1.4.0 (12) existe déjà chez Apple. Avec Expo, quatre causes reviennent :

- **Le profil utilisé n'a pas `autoIncrement`.** Si tu crées un profil à part pour TestFlight, comme celui de Nolera, remets-y l'option.
- **Le compteur distant est en retard.** Tu es passé en `remote` après des envois manuels : lance `eas build:version:set` avec le dernier numéro connu d'Apple.
- **Le commit a été oublié en mode local.** Le build suivant repart de l'ancien numéro.
- **Tu renvoies le même binaire.** Avec `eas submit`, choisis le nouveau build, pas l'ancien.

**La correction est toujours la même : un nouveau build avec un numéro plus haut.**

## « No builds available » : ton build n'apparaît pas

Le build est parti, mais ta fiche ne le propose pas. Vérifie dans cet ordre.

1. **Il est encore en traitement.** Apple traite chaque build avant de l'afficher et t'envoie un e-mail à la fin. [Expo](https://docs.expo.dev/submit/ios/) parle en général de 10 à 15 minutes. [Selon Apple](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata), au-delà de 24 heures en traitement, il faut ouvrir un ticket Feedback Assistant.
2. **Il attend ta déclaration de chiffrement.** C'est le statut Missing Compliance, détaillé plus bas.
3. **La version ne correspond pas.** Un build en 1.4.1 ne se range pas sous une fiche préparée en 1.5.0 dans App Store Connect. Aligne les deux.
4. **Une version est sortie entre-temps.** D'après [l'aide sur le choix du build](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit), la liste ne montre alors que les builds envoyés depuis cette sortie.
5. **C'est le testeur qui ne le voit pas.** Dans l'app TestFlight, « no builds available » veut souvent dire que le build n'est dans aucun groupe, attend la revue bêta ou a expiré. Le détail est dans [TestFlight pour tester ton app iPhone](https://devoria.fr/blog/testflight-tester-son-app-iphone).

### Les statuts à connaître

Les statuts qui expliquent le plus souvent un build absent, d'après [la liste d'Apple](https://developer.apple.com/help/app-store-connect/reference/app-build-statuses). Processing et Failed n'y figurent pas : ce sont les statuts d'envoi décrits dans [le suivi des builds](https://developer.apple.com/help/app-store-connect/manage-builds/view-builds-and-metadata).

| Statut             | Ce qu'il veut dire      | Ta correction           |
| ------------------ | ----------------------- | ----------------------- |
| Processing         | Apple traite le build   | Attendre l'e-mail       |
| Failed             | Erreur au traitement    | Lire l'erreur, renvoyer |
| Missing Compliance | Chiffrement non déclaré | Répondre ou Info.plist  |
| Invalid Binary     | Envoi non conforme      | Corriger, nouveau build |
| Expired            | 90 jours dépassés       | Nouveau build           |
| Ready to Submit    | Prêt pour test ou revue | L'ajouter à un groupe   |

### Déclarer le chiffrement une fois pour toutes

Sans la clé `ITSAppUsesNonExemptEncryption`, [Apple](https://developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption) te pose les questions de conformité à chaque nouvelle version. Avec Expo, le champ s'appelle `ios.config.usesNonExemptEncryption` :

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

`false` veut dire : pas de chiffrement, ou seulement un chiffrement exempté. [Apple précise](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations) que le chiffrement intégré au système, comme les connexions HTTPS, est en général exempté, et que la réponse couvre aussi tes bibliothèques. Mes trois apps déclarent `false`. **Ne mets `false` que si c'est vrai pour ton app : la déclaration t'engage.**

## Peut-on changer le numéro d'un build déjà envoyé ?

Non. Le numéro est inscrit dans le binaire signé : pour le corriger, il faut un nouveau build.

Ce que tu peux changer, c'est le build rattaché à ta version. Apple autorise un seul build par version, mais [tu peux le remplacer autant de fois que tu veux](https://developer.apple.com/help/app-store-connect/manage-builds/choose-a-build-to-submit) jusqu'à l'envoi en revue :

1. Ouvre la version dans App Store Connect, section Build.
2. Survole le build actuel et clique sur le bouton de suppression, le signe moins.
3. Clique sur le bouton d'ajout, le signe plus, choisis le bon build, puis enregistre.

Retirer un build d'une version ne le supprime pas de ton compte. Si la version est déjà en revue, [retire d'abord la soumission](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/remove-a-submission-from-review) : la revue repartira de zéro.

## Avant ton prochain envoi

Le numéro de build n'est qu'un des contrôles à l'envoi. L'image de build peut déclencher [ITMS-90725](https://devoria.fr/blog/itms-90725-sdk-version-xcode), et la signature a ses propres pièges, détaillés dans [certificat développeur iOS et provisioning profile](https://devoria.fr/blog/certificat-provisioning-profile-ios). La chaîne complète, du build à TestFlight, est dans [publier une app iOS sans Mac](https://devoria.fr/blog/publier-une-app-ios-sans-mac), et les délais de revue dans [délai de validation App Store](https://devoria.fr/blog/delai-validation-app-store). Toutes les étapes sont réunies sur la page [publier une application sur l'App Store](https://devoria.fr/expertise/publier-une-application-sur-app-store).

Si tu prépares ta première sortie, [fais le diagnostic gratuit](https://devoria.fr/diagnostic) : il te dit ce qui bloque dans ton projet et t'envoie ma checklist anti-refus Apple. Pour construire l'app, brancher les abonnements et la publier, le [Kit iOS](https://devoria.fr/kits/ios) suit le parcours en quatre étapes avec le code de départ de mes apps, à ton rythme.

## Questions fréquentes

### Quelle différence entre version et build number sur App Store Connect ?

La version est le numéro public de ta sortie, comme 1.4.0. Le build number identifie un binaire précis envoyé à Apple pour cette version. Tu peux envoyer plusieurs builds pour une même version, chacun avec son numéro.

### Faut-il changer le numéro de build à chaque envoi ?

Oui, pour une même version. Apple refuse un deuxième envoi avec le même couple version et numéro de build, c'est l'erreur ITMS-90189. Avec EAS, `autoIncrement` s'en charge à chaque build de production.

### Le numéro de build doit-il repartir à 1 à chaque version ?

Ce n'est pas obligatoire. Sur iPhone, Apple accepte un numéro plus bas pour une nouvelle version, car seul le couple doit être unique. Un compteur qui monte toujours reste plus simple à suivre.

### Comment changer le build number dans App Store Connect ?

Tu ne peux pas modifier le numéro d'un build déjà envoyé. Tu peux en revanche remplacer le build attaché à ta version, depuis la section Build de la fiche, tant qu'elle n'est pas en revue. Pour un nouveau numéro, refais un build.

### Pourquoi mon build n'apparaît pas dans App Store Connect ?

Le plus souvent, il est encore en traitement ou attend ta déclaration de chiffrement. Vérifie aussi que sa version correspond à celle de ta fiche. Au-delà de 24 heures en traitement, Apple demande d'ouvrir un ticket.


## Ton projet

[Kit Review](https://devoria.fr/kits/review-apple) : Tout ce que je vérifie avant d'envoyer une app à Apple, la même vérification pour Google Play, et trois skills qui font la relecture avec Claude Code. 49 €, paiement unique. Inclus : La checklist avant l'envoi ; Les refus que j'ai pris, et ce que j'ai corrigé ; Les notes pour le testeur ; Les skills de vérification. Prérequis : une app iPhone ou Android presque prête, et Claude Code ou Cursor. Téléchargement immédiat après le paiement.

[Kit iOS & Android Devoria](https://devoria.fr/kits/ios) : Le code de départ de mes apps, le parcours jusqu'à l'App Store et Google Play avec les messages à donner à Claude, et tous les kits. Claude part d'une app qui tourne déjà. 99 €, paiement unique. Inclus : Le code de départ de ton app ; Les styles visuels ; Le parcours pas à pas ; Kit Review ; Kit Captures ; Kit ASO ; Mises à jour à vie ; Bonus : la séance 1:1 à moitié prix. Prérequis : pour l'iPhone, un Mac avec Xcode 26 ou plus et un compte Apple Developer (99 $ par an) pour publier. Pour Android, Android Studio sur un Mac, un PC Windows ou Linux, et un compte Google Play Console (25 $, une fois). Et Claude Code (abonnement payant) ou Cursor. Téléchargement immédiat après le paiement.

[Diagnostic gratuit](https://devoria.fr/diagnostic) : quelques questions sur ton projet. Il dit ce qui te bloque vraiment, l'ordre des quatre étapes et le kit qui correspond. En laissant ton e-mail, tu reçois la checklist anti-refus Apple : les points vérifiés avant chaque envoi, tirés des refus reçus par les apps du studio.

[Une heure avec moi](https://devoria.fr/coaching) : On regarde ton app ou ton projet Claude, écran partagé : ce qui bloque, ce que je change en premier, et dans quel ordre. 100 € la séance d'une heure, en visio, paiement en une fois. Sujets : L'audit de ton app ; Ton travail avec Claude ; Ta fiche et ton paywall ; Un refus d'Apple.
