# eas submit iOS errors: common causes and fixes

> eas submit failing? The real EAS and App Store Connect messages, their cause and fix: ascAppId, API key, Apple agreement, ITMS codes.

Original page: [eas submit iOS errors: common causes and fixes](https://devoria.fr/en/blog/eas-submit-ios-errors-fixes)
Author: [Mehdi Azizi](https://devoria.fr/en/mehdi-azizi)
Published: 2026-11-04
Content last revised: 2026-11-04


When `eas submit --platform ios` fails, the message almost always tells you where to look. **Either your EAS configuration is incomplete, your Apple account is blocking, or Apple is rejecting the binary.** The first two cases take a few minutes to fix, with no new build. You can spot the third by its ITMS code, and it almost always needs a new build.

I publish my iOS apps, including Solys, TradaZen and Nolera, with Expo and EAS. The messages quoted here are copied from the EAS CLI source code, on [Expo's official GitHub repo](https://github.com/expo/eas-cli), reviewed on November 3, 2026. Expo's old forum now redirects to Discord, so the code remains the most reliable source. For the full walkthrough, from the `eas.json` file to submitting for review, read [EAS Submit iOS: publish an Expo app on the App Store](https://devoria.fr/en/blog/eas-submit-ios-publish-expo-app-store) first. Here, we fix things.

## What eas submit does, and what it needs

According to [Expo's documentation](https://docs.expo.dev/deploy/submit-to-app-stores/), the command uploads your `.ipa` file to App Store Connect. The build shows up in TestFlight once Apple has processed it, usually 10 to 15 minutes. **It does not submit your app for review**: you still do that in App Store Connect.

[Expo's iOS submission page](https://docs.expo.dev/submit/ios/) lists three prerequisites:

- **a paid Apple Developer account**, required for any upload to the App Store;
- **the bundle identifier** in `ios.bundleIdentifier`;
- **EAS CLI installed** and logged in to your Expo account.

To submit without any interaction, the same page adds two settings:

- **`ascAppId`** in the `submit` profile of `eas.json`, the number of your App Store Connect app record;
- **an App Store Connect API key**, managed by EAS or provided by you. Creating it, its role and revoking it are covered in [App Store Connect API key (.p8)](https://devoria.fr/en/blog/app-store-connect-api-key-p8).

The minimal profile fits in a few lines. The value is fake:

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

If EAS already stores your API key, this profile is enough. That's the case for most of my apps.

## Reading the message: three families of errors

Before looking for the fix, find the moment the command stops. This table is the grid I use for every failure.

| When it fails                            | Family            | New build?    |
| ---------------------------------------- | ----------------- | ------------- |
| Before anything is uploaded              | EAS configuration | No            |
| Connecting to Apple, creating the record | Apple account     | No            |
| After the upload, ITMS-90xxx code        | Binary rejected   | Almost always |

The details are on the submission page, in the Expo dashboard. [Expo recommends](https://docs.expo.dev/deploy/submit-to-app-stores/) reading the logs there and looking for the "Build Annotations" bubble, which flags common failure causes. In the terminal, the `--verbose` flag always prints the EAS Submit logs, according to [the EAS CLI reference](https://docs.expo.dev/eas/cli/).

## EAS configuration errors

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

You ran the command with `--non-interactive`, in CI for example, and your profile doesn't contain `ascAppId`. [The EAS CLI code](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/submit/ios/IosSubmitCommand.ts) stops there: it can't ask you anything, and it can't create the record for you.

**Fix: copy your record's number into `ascAppId`.** [Expo shows where to find it](https://github.com/expo/fyi/blob/main/asc-app-id.md): in App Store Connect, open your app, then App Information. It's the Apple ID field, under General Information, a number of about ten digits. It's not your Apple email address, and it's not your bundle identifier.

On Nolera, without `ascAppId`, the command asked me for an Apple Developer session, which expires. Since the number has been in `eas.json`, the submission doesn't ask for anything.

> Add `ascAppId` before the build, not after. Up to SDK 57, [the fingerprint computed by Expo](https://github.com/expo/expo/blob/main/packages/@expo/fingerprint/src/sourcer/Expo.ts) always includes `eas.json`. On Vigie, whose runtime version follows the `fingerprint` policy, adding this number after a build changed the fingerprint: an update published afterward would never have reached the installed build. Since SDK 58, the default fingerprint preset, `balanced`, ignores `eas.json`, according to [Expo's changelog](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."

Your profile doesn't contain a key, and EAS has none attached to your app. [Expo spells it out](https://docs.expo.dev/submit/ios/): in non-interactive mode, the command can't ask you for a key, so it fails with this message.

Two possible fixes:

- **Let EAS create and store the key.** Run `eas credentials --platform ios` once in interactive mode, on your machine, and let it set up an App Store Connect API key for your app.
- **Bring your own key** in `ascApiKeyPath`, `ascApiKeyIssuerId` and `ascApiKeyId`. According to [the eas.json reference](https://docs.expo.dev/eas/json/), these three fields accept environment variables, like `$ASC_API_KEY_PATH`.

On my latest app, the `--auto-submit` flag wanted an Apple ID to create its submission key. I put the three fields of my own key in the profile of my working copy, never committed. Then I submitted the finished build with `--id` and `--non-interactive`.

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

The variable contains something other than an app-specific password, often your actual Apple password. [EAS CLI](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/submit/ios/IosSubmitCommand.ts) checks this format before uploading anything.

According to [Apple's support page](https://support.apple.com/en-us/102654), you generate an app-specific password on account.apple.com, under App-Specific Passwords, with two-factor authentication turned on. It's revoked as soon as you change your Apple account password. **Expo considers this method [less secure than the API key](https://github.com/expo/fyi/blob/main/apple-app-specific-password.md), which is its default and recommended method.**

## Apple account errors

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

The full message starts with "You currently don't have access to this membership resource". On Apple's side, the raw response may contain "Unable to process request - PLA Update available". Recent EAS submission steps show "A required Apple agreement is missing or has expired" instead.

The cause is the same: Apple updated an agreement, and nobody accepted it. **Only the account owner, the Account Holder, can accept agreements**, according to [Apple's roles table](https://developer.apple.com/help/account/access/roles/). [The EAS code](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiClient.ts) tells them to go through the Business page in App Store Connect, then, if Apple prompts for it, through their account on developer.apple.com. Then run the command again. The paid apps agreement has its own guide: [Paid Apps Agreement in App Store Connect](https://devoria.fr/en/blog/paid-apps-agreement-statuses-w-8ben-first-payment).

### "App Store Connect rejected the API authentication credentials."

Apple answered with a 401 error, `NOT_AUTHORIZED`. [EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiClient.ts) lists three causes: a key that's no longer active, a key from another App Store Connect account, or a wrong Key ID, key content or Issuer ID.

Check both identifiers in App Store Connect, under Users and Access, Integrations tab. According to [Apple](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests), the Issuer ID is shown at the top of the page, and the Key ID in the list of active keys. **A revoked key can never be reactivated.** [Apple shows it](https://developer.apple.com/documentation/appstoreconnectapi/revoking-api-keys) for 30 days under Revoked: you need to generate a new one.

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

The record targeted by `ascAppId` can't be found with your key. [EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiUtils.ts) asks you to check that number, and to make sure the key has access to the app in the right account. It even lists a few apps visible with that key. With Apple's upload tools, the same problem shows up as "No suitable application records were found".

Three causes come up, two of them noted in [this Apple forums thread](https://developer.apple.com/forums/thread/106806):

- **The record doesn't exist.** Create it in App Store Connect, or remove `ascAppId` so the command creates it.
- **The number comes from another account.** You copied the `ascAppId` from another team, or another project.
- **The user doesn't have access to the app.** An App Manager or a Developer can be limited to specific apps. A team key, on the other hand, [has access to every app](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api) in the account.

### "… is not available to team" or "… is not available to provider"

This message shows up when EAS creates the record for you, because there's no `ascAppId`. The bundle identifier is already taken by another team. [EAS asks you](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/credentials/ios/appstore/ensureAppExists.ts) to change it in your app config, then run it again.

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

This isn't a failure. When the name is already taken on the App Store, EAS adds six random characters and tries again, up to five times. You'll rename the record later in App Store Connect. To avoid it, set `appName` and `language` in the profile before the first submission: without `language`, [the primary language defaults to `en-US`](https://docs.expo.dev/eas/json/).

## Binary errors: ITMS codes

After the upload, Apple processes the build. If it rejects it, the log cites one or more ITMS codes. Here are the ones [the EAS upload step](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/functions/uploadToAsc.ts) recognizes and translates:

| ITMS code                  | What Apple rejects                     | Fix                   |
| -------------------------- | -------------------------------------- | --------------------- |
| 90189                      | Build number already used              | `autoIncrement`       |
| 90062, 90186, 90478        | Version closed or already superseded   | Bump `version`        |
| 90683                      | Missing purpose string                 | `ios.infoPlist`       |
| 90725                      | iOS SDK too old                        | iOS image or Expo SDK |
| 90054, 90055               | Bundle doesn't match the target record | Fix `ascAppId`        |
| 90022, 90023, 90391, 90713 | Icons missing or declared wrong        | Review the icons      |
| 90771                      | Background task identifiers missing    | `ios.infoPlist`       |

Three notes from these messages:

- **The build number is unique per version.** For 90189, EAS recommends `"autoIncrement": true` in `eas.json`. It's all in [build number and version](https://devoria.fr/en/blog/app-store-connect-build-number-version).
- **For 90725**, EAS suggests picking a newer iOS image in `eas.json`, and if needed moving to a supported Expo SDK.
- **For 90771**, your Info.plist declares the `processing` background mode, but not the `BGTaskSchedulerPermittedIdentifiers` key.

Except for 90054 and 90055, where you just need to target the right record or another build, **the fix touches the binary: make a new build, then submit it again.** Two codes have their own guide: [ITMS-90683 with Expo](https://devoria.fr/en/blog/itms-90683-missing-purpose-string-expo) and [ITMS-90725](https://devoria.fr/en/blog/itms-90725-sdk-version-issue-expo).

At the end of September 2026, a Solys build was rejected on delivery for ITMS-90683. I had removed a photos purpose string while cleaning up the config file. Solys doesn't use photos, but a library in the project calls the iOS Photos API. **Apple analyzes the binary, not actual usage:** since then, I never remove those strings.

The Missing Compliance status, on the other hand, isn't a submission error. Your encryption declaration is missing, as explained in [the EAS publishing guide](https://devoria.fr/en/blog/eas-submit-ios-publish-expo-app-store).

## My checklist before every submission

- `ascAppId` is in the `submit` profile, added before the build.
- The API key is managed by EAS, or its three fields point to a `.p8` stored outside the repo.
- The Account Holder has accepted the latest agreements in App Store Connect.
- `autoIncrement` is on, with `"appVersionSource": "remote"`, [recommended by Expo](https://docs.expo.dev/build-reference/app-versions/) since EAS CLI 12.
- The `version` is higher than the last approved version.
- Every sensitive API in the binary has its purpose string.
- For a new app, `appName` and `language` are set before the first submission.

## Submitting your first app without getting stuck

The command is just one step. The [iOS & Android Kit](https://devoria.fr/en/kits/ios) starts from the Starter Code of my apps, subscriptions included, and walks you through four steps to the App Store, at your own pace.

If you're preparing your first release, [take the free diagnostic](https://devoria.fr/en/diagnostic): it tells you what's really holding you back and sends you my Apple anti-rejection checklist. For the listing, screenshots and approval, the page [publish an app on the App Store](https://devoria.fr/en/expertise/publish-an-app-on-the-app-store) covers every step.

## Frequently asked questions

### Why does eas submit only fail in CI?

In `--non-interactive` mode, the command can't ask you anything. It needs `ascAppId` in the profile and an API key already attached to the app, or its three fields in `eas.json`. On your machine, it would have asked you those questions.

### Do I need a new build after an eas submit error?

Only if Apple rejects the binary, with an ITMS code. Exception: for ITMS-90054 and 90055, the build targeted the wrong record, so you just submit it again to the right one. Configuration and account errors are fixed in `eas.json`, in App Store Connect or in your Apple account. Then you submit the same build again, for example with `--latest` or `--id`.

### Where can I see the logs of an EAS Submit upload?

On the submission page, in the Expo dashboard. Expo recommends reading the logs there and the "Build Annotations" bubble. In the terminal, add `--verbose` to always print the logs.

### Can I use eas submit with a free Apple account?

No. Expo requires a paid Apple Developer account to submit an app to the App Store. The free account lets you test on your own iPhone, not use App Store Connect.

### What role should the API key have for eas submit?

Expo's guide gives the key the Admin role. According to Apple's roles table, uploading builds is also open to the App Manager and Developer roles. My Expo builds run with a team key that has the App Manager role. Only the Account Holder and Admins can generate a team key.

### What does "Increment Build Number" mean in EAS?

Apple rejected the build with code ITMS-90189: that build number already exists for this version. Turn on `"autoIncrement": true` in `eas.json`, or bump `ios.buildNumber`, then make a new build.


## Your project

[Review Kit](https://devoria.fr/en/kits/app-review): My App Store review checklist, the Apple rejections I fixed, a Google Play checklist and three Claude Code skills. $55.

[iOS & Android Kit](https://devoria.fr/en/kits/ios): Build your iPhone and Android app with Claude Code: the starter code from my apps, the path all the way to the stores, and every kit. $109.

[Diagnostic: what's between you and your iPhone app](https://devoria.fr/en/diagnostic): 7 questions, 60 seconds: find out what's really stopping you from publishing your iPhone app, get your 4-step path and the kit that fits you.
