# eas submit iOS : les erreurs fréquentes et leur correction

> eas submit échoue ? Les vrais messages d'EAS et d'App Store Connect, leur cause et leur correction : ascAppId, clé API, contrat Apple, codes ITMS.

Page originale : [eas submit iOS : les erreurs fréquentes et leur correction](https://devoria.fr/blog/expo-envoi-app-store-connect-erreurs)
Auteur : [Mehdi Azizi](https://devoria.fr/mehdi-azizi)
Publication : 2026-11-04
Dernière révision du contenu : 2026-11-04


Quand `eas submit --platform ios` échoue, le message dit presque toujours où regarder. **Soit ta configuration EAS est incomplète, soit ton compte Apple bloque, soit Apple refuse le binaire.** Les deux premiers cas se corrigent en quelques minutes, sans nouveau build. Le troisième se reconnaît à un code ITMS, et il demande presque toujours un nouveau build.

Je publie mes apps iOS, dont Solys, TradaZen et Nolera, avec Expo et EAS. Les messages cités ici sont copiés du code source d'EAS CLI, sur [le dépôt GitHub officiel d'Expo](https://github.com/expo/eas-cli), relu le 3 novembre 2026. L'ancien forum d'Expo renvoie désormais vers Discord : le code reste la source la plus sûre. Pour le parcours complet, du fichier `eas.json` à l'envoi en revue, lis d'abord [EAS Submit iOS : publier une app Expo sur l'App Store](https://devoria.fr/blog/publier-app-expo-app-store-eas). Ici, on répare.

## Ce que fait eas submit, et ce qu'il lui faut

D'après [la documentation d'Expo](https://docs.expo.dev/deploy/submit-to-app-stores/), la commande envoie ton fichier `.ipa` à App Store Connect. Le build apparaît dans TestFlight après le traitement par Apple, en général 10 à 15 minutes. **Elle ne soumet pas ton app à la revue** : ce geste reste à faire dans App Store Connect.

[La page d'Expo sur l'envoi iOS](https://docs.expo.dev/submit/ios/) liste trois prérequis :

- **un compte Apple Developer payant**, exigé pour tout envoi vers l'App Store ;
- **l'identifiant de bundle** dans `ios.bundleIdentifier` ;
- **EAS CLI installé** et connecté à ton compte Expo.

Pour envoyer sans interaction, la même page ajoute deux réglages :

- **`ascAppId`** dans le profil `submit` de `eas.json`, le numéro de ta fiche App Store Connect ;
- **une clé API App Store Connect**, gérée par EAS ou fournie par toi. Sa création, son rôle et sa révocation sont détaillés dans [clé API App Store Connect (.p8)](https://devoria.fr/blog/cle-api-app-store-connect-p8).

Le profil minimal tient en quelques lignes. La valeur est factice :

```json
{
  "submit": {
    "production": {
      "ios": {
        "ascAppId": "1234567890"
      }
    }
  }
}
```

Si EAS garde déjà ta clé API, ce profil suffit. C'est le cas sur la plupart de mes apps.

## Lire le message : trois familles d'erreurs

Avant de chercher la correction, repère le moment où la commande s'arrête. Ce tableau est la grille que j'applique à chaque échec.

| Moment de l'échec                       | Famille           | Nouveau build ?  |
| --------------------------------------- | ----------------- | ---------------- |
| Avant tout envoi                        | Configuration EAS | Non              |
| Connexion à Apple, création de la fiche | Compte Apple      | Non              |
| Après l'envoi, code ITMS-90xxx          | Binaire refusé    | Presque toujours |

Le détail se lit sur la page de la soumission, dans le tableau de bord d'Expo. [Expo conseille](https://docs.expo.dev/deploy/submit-to-app-stores/) d'y lire les journaux et de repérer la bulle « Build Annotations », qui signale les causes d'échec courantes. Dans le terminal, l'option `--verbose` affiche toujours les journaux d'EAS Submit, d'après [la référence d'EAS CLI](https://docs.expo.dev/eas/cli/).

## Les erreurs de configuration EAS

### « Set ascAppId in the submit profile (eas.json) or re-run this command in interactive mode. »

Tu as lancé la commande avec `--non-interactive`, en intégration continue par exemple, et ton profil ne contient pas `ascAppId`. [Le code d'EAS CLI](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/submit/ios/IosSubmitCommand.ts) s'arrête alors : il ne peut ni te poser de question, ni créer la fiche à ta place.

**Correction : recopie le numéro de ta fiche dans `ascAppId`.** [Expo indique où le trouver](https://github.com/expo/fyi/blob/main/asc-app-id.md) : dans App Store Connect, ouvre ton app, puis App Information. C'est le champ Apple ID, sous General Information, un nombre d'une dizaine de chiffres. Ce n'est ni ton adresse e-mail Apple, ni ton identifiant de bundle.

Sur Nolera, sans `ascAppId`, la commande me réclamait une session Apple Developer, qui expire. Depuis que le numéro est dans `eas.json`, l'envoi ne demande plus rien.

> Ajoute `ascAppId` avant le build, pas après. Jusqu'au SDK 57, [l'empreinte calculée par Expo](https://github.com/expo/expo/blob/main/packages/@expo/fingerprint/src/sourcer/Expo.ts) inclut toujours `eas.json`. Sur Vigie, dont la version d'exécution suit la politique `fingerprint`, ajouter ce numéro après un build a changé l'empreinte : une mise à jour publiée ensuite n'aurait jamais atteint le build installé. Depuis le SDK 58, le préréglage par défaut de l'empreinte, `balanced`, ignore `eas.json`, d'après [le journal des versions d'Expo](https://github.com/expo/expo/blob/main/packages/@expo/fingerprint/CHANGELOG.md).

### « App Store Connect API Keys cannot be set up in --non-interactive mode. »

Ton profil ne contient pas de clé, et EAS n'en a aucune rattachée à ton app. [Expo le précise](https://docs.expo.dev/submit/ios/) : en mode non interactif, la commande ne peut pas te demander de clé, et elle échoue avec ce message.

Deux corrections possibles :

- **Laisse EAS créer et garder la clé.** Lance une fois `eas credentials --platform ios` en mode interactif, sur ta machine, et laisse-le configurer une clé API App Store Connect pour ton app.
- **Apporte ta propre clé** dans `ascApiKeyPath`, `ascApiKeyIssuerId` et `ascApiKeyId`. D'après [la référence d'eas.json](https://docs.expo.dev/eas/json/), ces trois champs acceptent des variables d'environnement, comme `$ASC_API_KEY_PATH`.

Sur ma dernière app, l'option `--auto-submit` voulait un identifiant Apple pour créer sa clé d'envoi. J'ai mis les trois champs de ma propre clé dans le profil de ma copie de travail, jamais commitée. Puis j'ai envoyé le build terminé avec `--id` et `--non-interactive`.

### « EXPO_APPLE_APP_SPECIFIC_PASSWORD must be in the format xxxx-xxxx-xxxx-xxxx, where x is a lowercase letter. »

La variable contient autre chose qu'un mot de passe d'app, souvent ton mot de passe Apple lui-même. [EAS CLI](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/submit/ios/IosSubmitCommand.ts) vérifie ce format avant tout envoi.

Selon [l'aide d'Apple](https://support.apple.com/en-us/102654), un mot de passe d'app se génère sur account.apple.com, rubrique App-Specific Passwords, avec la double authentification activée. Il est révoqué dès que tu changes le mot de passe de ton compte Apple. **Expo juge cette méthode [moins sûre que la clé API](https://github.com/expo/fyi/blob/main/apple-app-specific-password.md), sa méthode par défaut et recommandée.**

## Les erreurs du compte Apple

### « … agree to the latest Program License Agreement in your developer account. »

Le message complet commence par « You currently don't have access to this membership resource ». Côté Apple, la réponse brute peut contenir « Unable to process request - PLA Update available ». Les étapes d'envoi récentes d'EAS affichent plutôt « A required Apple agreement is missing or has expired ».

La cause est la même : Apple a mis à jour un contrat, et personne ne l'a accepté. **Seul le titulaire du compte, l'Account Holder, peut accepter les contrats**, d'après [le tableau des rôles d'Apple](https://developer.apple.com/help/account/access/roles/). [Le code d'EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiClient.ts) lui demande de passer par la page Business d'App Store Connect, puis, si Apple le propose, par son compte sur developer.apple.com. Relance ensuite la commande. Le contrat des apps payantes a son guide : [Paid Apps Agreement dans App Store Connect](https://devoria.fr/blog/paid-apps-agreement-app-store-connect).

### « App Store Connect rejected the API authentication credentials. »

Apple a répondu par une erreur 401, `NOT_AUTHORIZED`. [EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiClient.ts) cite trois causes : une clé qui n'est plus active, une clé d'un autre compte App Store Connect, ou un Key ID, un contenu de clé ou un Issuer ID erroné.

Vérifie les deux identifiants dans App Store Connect, menu Users and Access, onglet Integrations. D'après [Apple](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests), l'Issuer ID s'affiche en haut de la page, et le Key ID dans la liste des clés actives. **Une clé révoquée ne se réactive jamais.** [Apple l'affiche](https://developer.apple.com/documentation/appstoreconnectapi/revoking-api-keys) 30 jours sous Revoked : il faut en générer une nouvelle.

### « App Store Connect app for application identifier … was not found. »

La fiche visée par `ascAppId` est introuvable avec ta clé. [EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiUtils.ts) te demande de vérifier ce numéro, et que la clé a bien accès à l'app dans le bon compte. Il liste même quelques apps visibles avec cette clé. Avec les outils d'envoi d'Apple, le même problème s'affiche sous la forme « No suitable application records were found ».

Trois causes reviennent, dont deux relevées dans [ce fil des forums d'Apple](https://developer.apple.com/forums/thread/106806) :

- **La fiche n'existe pas.** Crée-la dans App Store Connect, ou retire `ascAppId` pour que la commande la crée.
- **Le numéro vient d'un autre compte.** Tu as copié l'`ascAppId` d'une autre équipe, ou d'un autre projet.
- **L'utilisateur n'a pas accès à l'app.** Un App Manager ou un Developer peut être limité à certaines apps. Une clé d'équipe, elle, [accède à toutes les apps](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api) du compte.

### « … is not available to team » ou « … is not available to provider »

Ce message apparaît quand EAS crée la fiche à ta place, faute d'`ascAppId`. L'identifiant de bundle est déjà pris par une autre équipe. [EAS te demande](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/credentials/ios/appstore/ensureAppExists.ts) de le changer dans la configuration de ton app, puis de relancer.

### « App name "…" is already taken. Using generated name "…" »

Ce n'est pas un échec. Quand le nom est déjà pris sur l'App Store, EAS ajoute six caractères au hasard et réessaie, jusqu'à cinq fois. Tu renommeras la fiche plus tard dans App Store Connect. Pour l'éviter, renseigne `appName` et `language` dans le profil avant le premier envoi : sans `language`, [la langue principale vaut `en-US`](https://docs.expo.dev/eas/json/).

## Les erreurs du binaire : les codes ITMS

Après l'envoi, Apple traite le build. S'il le refuse, le journal cite un ou plusieurs codes ITMS. Voici ceux que [l'étape d'envoi d'EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/functions/uploadToAsc.ts) reconnaît et traduit :

| Code ITMS                  | Ce qu'Apple refuse                     | Correction            |
| -------------------------- | -------------------------------------- | --------------------- |
| 90189                      | Numéro de build déjà pris              | `autoIncrement`       |
| 90062, 90186, 90478        | Version fermée ou déjà dépassée        | Monter `version`      |
| 90683                      | Phrase d'autorisation absente          | `ios.infoPlist`       |
| 90725                      | SDK iOS trop ancien                    | Image iOS ou SDK Expo |
| 90054, 90055               | Bundle différent de la fiche visée     | Corriger `ascAppId`   |
| 90022, 90023, 90391, 90713 | Icônes absentes ou mal déclarées       | Revoir les icônes     |
| 90771                      | Identifiants de tâches de fond absents | `ios.infoPlist`       |

Trois précisions tirées de ces messages :

- **Le numéro de build est unique par version.** Pour 90189, EAS recommande `"autoIncrement": true` dans `eas.json`. Tout est dans [numéro de build et version](https://devoria.fr/blog/numero-de-build-version-app-store-connect).
- **Pour 90725**, EAS conseille de choisir une image iOS plus récente dans `eas.json`, et si besoin de passer à un SDK d'Expo pris en charge.
- **Pour 90771**, ton Info.plist déclare le mode d'arrière-plan `processing`, mais pas la clé `BGTaskSchedulerPermittedIdentifiers`.

Sauf pour 90054 et 90055, où il suffit de viser la bonne fiche ou un autre build, **la correction touche le binaire : refais un build, puis renvoie-le.** Deux codes ont leur guide : [ITMS-90683 avec Expo](https://devoria.fr/blog/itms-90683-missing-purpose-string-expo) et [ITMS-90725](https://devoria.fr/blog/itms-90725-sdk-version-xcode).

Fin septembre 2026, un build de Solys a été refusé à la livraison pour ITMS-90683. J'avais retiré une phrase d'autorisation sur les photos pendant un ménage du fichier de configuration. Solys n'utilise pas les photos, mais une bibliothèque du projet appelle l'API Photos d'iOS. **Apple analyse le binaire, pas l'usage réel :** depuis, je ne retire plus jamais ces phrases.

Le statut Missing Compliance, lui, n'est pas une erreur d'envoi. Il manque ta déclaration sur le chiffrement, expliquée dans [le guide de publication avec EAS](https://devoria.fr/blog/publier-app-expo-app-store-eas).

## Ma check-list avant chaque envoi

- `ascAppId` est dans le profil `submit`, ajouté avant le build.
- La clé API est gérée par EAS, ou ses trois champs pointent vers un `.p8` rangé hors du dépôt.
- L'Account Holder a accepté les derniers contrats dans App Store Connect.
- `autoIncrement` est actif, avec `"appVersionSource": "remote"`, [recommandé par Expo](https://docs.expo.dev/build-reference/app-versions/) depuis EAS CLI 12.
- La `version` est supérieure à la dernière version approuvée.
- Chaque API sensible présente dans le binaire a sa phrase d'autorisation.
- Pour une app neuve, `appName` et `language` sont renseignés avant le premier envoi.

## Envoyer ta première app sans rester bloqué

La commande n'est qu'une étape. Le [Kit iOS](https://devoria.fr/kits/ios) part du code de départ de mes apps, abonnements compris, et suit quatre étapes jusqu'à l'App Store, à ton rythme.

Si tu prépares ta première sortie, [fais ton diagnostic gratuit](https://devoria.fr/diagnostic) : il te dit ce qui te bloque vraiment et t'envoie ma checklist anti-refus Apple. Pour la fiche, les captures et la validation, la page [publier une application sur l'App Store](https://devoria.fr/expertise/publier-une-application-sur-app-store) reprend chaque étape.

## Questions fréquentes

### Pourquoi eas submit échoue-t-il seulement en intégration continue ?

En mode `--non-interactive`, la commande ne peut rien te demander. Il lui faut `ascAppId` dans le profil et une clé API déjà rattachée à l'app, ou ses trois champs dans `eas.json`. Sur ta machine, elle t'aurait posé ces questions.

### Faut-il refaire un build après une erreur d'eas submit ?

Seulement si Apple refuse le binaire, avec un code ITMS. Exception : pour ITMS-90054 et 90055, le build visait la mauvaise fiche, il suffit de le renvoyer vers la bonne. Les erreurs de configuration et de compte se corrigent dans `eas.json`, dans App Store Connect ou dans ton compte Apple. Tu renvoies ensuite le même build, par exemple avec `--latest` ou `--id`.

### Où voir les journaux d'un envoi EAS Submit ?

Sur la page de la soumission, dans le tableau de bord d'Expo. Expo conseille d'y lire les journaux et la bulle « Build Annotations ». Dans le terminal, ajoute `--verbose` pour afficher toujours les journaux.

### Peut-on utiliser eas submit avec un compte Apple gratuit ?

Non. Expo exige un compte Apple Developer payant pour envoyer une app vers l'App Store. Le compte gratuit permet de tester sur ton propre iPhone, pas d'utiliser App Store Connect.

### Quel rôle donner à la clé API pour eas submit ?

Le guide d'Expo donne le rôle Admin à la clé. D'après le tableau des rôles d'Apple, l'envoi de builds est aussi ouvert aux rôles App Manager et Developer. Mes builds Expo tournent avec une clé d'équipe au rôle App Manager. Seuls l'Account Holder et les Admins peuvent générer une clé d'équipe.

### Que veut dire « Increment Build Number » dans EAS ?

Apple a refusé le build avec le code ITMS-90189 : ce numéro de build existe déjà pour cette version. Active `"autoIncrement": true` dans `eas.json`, ou monte `ios.buildNumber`, puis refais un build.


## 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.
