# eas submit iOS 常見錯誤與修正方法

> eas submit 失敗？EAS 與 App Store Connect 的實際錯誤訊息、原因與修正：ascAppId、API 金鑰、Apple 合約、ITMS 代碼。

原始頁面：[eas submit iOS 常見錯誤與修正方法](https://devoria.fr/zh-hant/blog/eas-submit-ios-common-errors-fixes)
作者：[Mehdi Azizi](https://devoria.fr/zh-hant/mehdi-azizi)
發布日期：2026-11-04
內容最後修訂：2026-11-04


當 `eas submit --platform ios` 失敗時，錯誤訊息幾乎都會告訴你該往哪裡找。**不是你的 EAS 設定不完整，就是你的 Apple 帳號卡住了，要不然就是 Apple 拒收了你的二進位檔。**前兩種情況幾分鐘就能修好，不用重新 build。第三種可以從 ITMS 代碼認出來，而且幾乎都需要重新 build。

我用 Expo 和 EAS 發布我的 iOS app，包括 Solys、TradaZen 和 Nolera。這裡引用的訊息都是從 EAS CLI 的原始碼複製來的，來源是 [Expo 官方 GitHub 儲存庫](https://github.com/expo/eas-cli)，我在 2026 年 11 月 3 日重新看過。Expo 舊論壇現在已經導向 Discord，所以原始碼仍是最可靠的來源。如果要看完整流程，從 `eas.json` 檔案到送審，請先讀 [EAS Submit iOS：把 Expo app 發布到 App Store](https://devoria.fr/zh-hant/blog/eas-submit-ios-expo-app-store)。這篇專門講修錯。

## eas submit 做了什麼，又需要什麼

根據 [Expo 文件](https://docs.expo.dev/deploy/submit-to-app-stores/)，這個指令會把你的 `.ipa` 檔案上傳到 App Store Connect。Apple 處理完之後，build 會出現在 TestFlight，通常要 10 到 15 分鐘。**它不會把你的 app 送去審查**：這一步還是要在 App Store Connect 裡自己做。

[Expo 關於 iOS 上傳的頁面](https://docs.expo.dev/submit/ios/)列出三個前提：

- **付費的 Apple Developer 帳號**，任何上傳到 App Store 的動作都需要；
- **bundle identifier**，寫在 `ios.bundleIdentifier`；
- **已安裝 EAS CLI**，並登入你的 Expo 帳號。

若要在非互動模式下上傳，同一頁還補充了兩項設定：

- **`ascAppId`**，寫在 `eas.json` 的 `submit` 設定檔裡，也就是你 App Store Connect 頁面的編號；
- **一把 App Store Connect API 金鑰**，可以由 EAS 管理，也可以自己提供。建立、角色與撤銷的細節請看 [App Store Connect API 金鑰（.p8）](https://devoria.fr/zh-hant/blog/app-store-connect-api-key-p8-create-use)。

最精簡的設定檔只要幾行。下面的值是假的：

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

如果 EAS 已經保管你的 API 金鑰，這個設定檔就夠了。我大部分的 app 都是這樣。

## 讀懂訊息：三類錯誤

找修正方法之前，先看指令是在哪個時間點停下來的。這張表是我每次失敗時都會套用的判斷方式。

| 失敗時間點                | 類別         | 需要重新 build？ |
| ------------------------- | ------------ | ---------------- |
| 尚未上傳任何東西之前      | EAS 設定     | 不用             |
| 連線 Apple、建立 app 頁面 | Apple 帳號   | 不用             |
| 上傳之後，出現 ITMS-90xxx | 二進位檔被拒 | 幾乎都要         |

詳細內容可以在 Expo 儀表板裡該次提交的頁面查看。[Expo 建議](https://docs.expo.dev/deploy/submit-to-app-stores/)在那裡讀日誌，並留意「Build Annotations」提示框，它會標出常見的失敗原因。在終端機裡，根據 [EAS CLI 參考文件](https://docs.expo.dev/eas/cli/)，加上 `--verbose` 選項就會一律顯示 EAS Submit 的日誌。

## EAS 設定錯誤

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

你用 `--non-interactive` 執行指令（例如在 CI 裡），而設定檔裡沒有 `ascAppId`。這時 [EAS CLI 的程式碼](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/submit/ios/IosSubmitCommand.ts)會直接停止：它沒辦法問你問題，也沒辦法替你建立 app 頁面。

**修正：把你 app 頁面的編號抄進 `ascAppId`。**[Expo 說明了在哪裡找](https://github.com/expo/fyi/blob/main/asc-app-id.md)：在 App Store Connect 打開你的 app，再進入 App Information。就是 General Information 底下的 Apple ID 欄位，大約十位數的數字。它不是你的 Apple 電子郵件，也不是你的 bundle identifier。

在 Nolera 上，沒有 `ascAppId` 時，指令會要我登入 Apple Developer 工作階段，而那個工作階段會過期。自從把編號寫進 `eas.json`，上傳就再也不會問任何東西了。

> 在 build 之前加上 `ascAppId`，不要在 build 之後。到 SDK 57 為止，[Expo 計算的指紋](https://github.com/expo/expo/blob/main/packages/@expo/fingerprint/src/sourcer/Expo.ts)一律包含 `eas.json`。Vigie 的 runtime version 採用 `fingerprint` 策略，我在 build 之後才加這個編號，指紋就變了：之後發布的更新永遠不會送到已安裝的 build。根據 [Expo 的版本紀錄](https://github.com/expo/expo/blob/main/packages/@expo/fingerprint/CHANGELOG.md)，從 SDK 58 起，指紋的預設設定 `balanced` 會忽略 `eas.json`。

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

你的設定檔裡沒有金鑰，EAS 也沒有任何金鑰綁定你的 app。[Expo 有說明](https://docs.expo.dev/submit/ios/)：在非互動模式下，指令無法向你索取金鑰，就會帶著這個訊息失敗。

有兩種修正方式：

- **讓 EAS 建立並保管金鑰。**在你的電腦上以互動模式執行一次 `eas credentials --platform ios`，讓它替你的 app 設定一把 App Store Connect API 金鑰。
- **自備金鑰**，填入 `ascApiKeyPath`、`ascApiKeyIssuerId` 和 `ascApiKeyId`。根據 [eas.json 參考文件](https://docs.expo.dev/eas/json/)，這三個欄位都接受環境變數，例如 `$ASC_API_KEY_PATH`。

在我最新的 app 上，`--auto-submit` 選項要我提供 Apple ID 來建立它的上傳金鑰。我把自己金鑰的三個欄位放進工作副本的設定檔裡，從來不 commit。然後用 `--id` 和 `--non-interactive` 上傳已完成的 build。

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

這個變數裡放的不是 App 專用密碼，常常是你的 Apple 密碼本身。[EAS CLI](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/submit/ios/IosSubmitCommand.ts) 在上傳之前就會檢查這個格式。

根據 [Apple 支援說明](https://support.apple.com/en-us/102654)，App 專用密碼要在 account.apple.com 的 App-Specific Passwords 區塊產生，而且要開啟雙重認證。只要你更改 Apple 帳號密碼，它就會被撤銷。**Expo 認為這種方式[不如 API 金鑰安全](https://github.com/expo/fyi/blob/main/apple-app-specific-password.md)，API 金鑰才是它預設且推薦的方式。**

## Apple 帳號錯誤

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

完整訊息的開頭是「You currently don't have access to this membership resource」。Apple 端的原始回應可能包含「Unable to process request - PLA Update available」。EAS 較新的上傳步驟則會顯示「A required Apple agreement is missing or has expired」。

原因都一樣：Apple 更新了某份合約，但沒有人同意。根據 [Apple 的角色表](https://developer.apple.com/help/account/access/roles/)，**只有帳號持有人（Account Holder）能同意合約**。[EAS 的程式碼](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiClient.ts)會請他到 App Store Connect 的 Business 頁面處理，若 Apple 有要求，再到 developer.apple.com 的帳號頁面處理。然後重新執行指令。付費 app 的合約有獨立的指南：[App Store Connect 的 Paid Apps Agreement](https://devoria.fr/zh-hant/blog/paid-apps-agreement-status-w-8ben-first-payment)。

### 「App Store Connect rejected the API authentication credentials.」

Apple 回傳了 401 錯誤，`NOT_AUTHORIZED`。[EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiClient.ts) 列出三種原因：金鑰已失效、金鑰屬於另一個 App Store Connect 帳號，或是 Key ID、金鑰內容、Issuer ID 有誤。

到 App Store Connect 的 Users and Access 選單、Integrations 分頁檢查這兩個識別碼。根據 [Apple](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests)，Issuer ID 顯示在頁面上方，Key ID 則在有效金鑰清單裡。**被撤銷的金鑰永遠無法重新啟用。**[Apple 會把它](https://developer.apple.com/documentation/appstoreconnectapi/revoking-api-keys)在 Revoked 底下顯示 30 天：你必須重新產生一把。

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

用你的金鑰找不到 `ascAppId` 指向的 app 頁面。[EAS](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiUtils.ts) 會請你檢查這個編號，並確認金鑰在正確的帳號裡確實有這個 app 的權限。它甚至會列出幾個用這把金鑰看得到的 app。用 Apple 自己的上傳工具時，同樣的問題會顯示成「No suitable application records were found」。

常見原因有三個，其中兩個出自 [Apple 論壇的這篇討論](https://developer.apple.com/forums/thread/106806)：

- **app 頁面不存在。**在 App Store Connect 建立它，或拿掉 `ascAppId`，讓指令幫你建立。
- **編號來自另一個帳號。**你複製了別的團隊或別的專案的 `ascAppId`。
- **使用者沒有這個 app 的權限。**App Manager 或 Developer 可能只被開放部分 app。團隊金鑰則[可以存取帳號內所有 app](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api)。

### 「… is not available to team」或「… is not available to provider」

這個訊息會在 EAS 因為沒有 `ascAppId` 而替你建立 app 頁面時出現。bundle identifier 已經被其他團隊用走了。[EAS 會請你](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/src/credentials/ios/appstore/ensureAppExists.ts)在 app 設定裡更改它，然後重新執行。

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

這不是失敗。當名稱在 App Store 上已被使用，EAS 會隨機加上六個字元再試一次，最多五次。之後你可以在 App Store Connect 裡改名。要避免這種情況，請在第一次上傳前，在設定檔裡填好 `appName` 和 `language`：沒有 `language` 的話，[主要語言會是 `en-US`](https://docs.expo.dev/eas/json/)。

## 二進位檔錯誤：ITMS 代碼

上傳之後，Apple 會處理 build。如果被拒，日誌會列出一個或多個 ITMS 代碼。以下是 [EAS 上傳步驟](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/functions/uploadToAsc.ts)能辨識並解讀的代碼：

| ITMS 代碼                  | Apple 拒絕的原因           | 修正方式              |
| -------------------------- | -------------------------- | --------------------- |
| 90189                      | build 編號已被使用         | `autoIncrement`       |
| 90062, 90186, 90478        | 版本已關閉或已被超過       | 提高 `version`        |
| 90683                      | 缺少權限說明文字           | `ios.infoPlist`       |
| 90725                      | iOS SDK 太舊               | iOS 映像檔或 Expo SDK |
| 90054, 90055               | bundle 與目標 app 頁面不符 | 修正 `ascAppId`       |
| 90022, 90023, 90391, 90713 | 圖示缺少或宣告錯誤         | 檢查圖示              |
| 90771                      | 缺少背景任務識別碼         | `ios.infoPlist`       |

從這些訊息整理出三點補充：

- **build 編號在同一版本內必須唯一。**遇到 90189，EAS 建議在 `eas.json` 加上 `"autoIncrement": true`。詳情請看 [build 編號與版本](https://devoria.fr/zh-hant/blog/app-store-connect-build-number-version)。
- **遇到 90725**，EAS 建議在 `eas.json` 選用較新的 iOS 映像檔，必要時升級到仍受支援的 Expo SDK。
- **遇到 90771**，代表你的 Info.plist 宣告了 `processing` 背景模式，卻沒有 `BGTaskSchedulerPermittedIdentifiers` 這個鍵。

除了 90054 和 90055 只要指向正確的 app 頁面或換一個 build 之外，**修正都會動到二進位檔：重新 build，再重新上傳。**有兩個代碼有專屬指南：[Expo 的 ITMS-90683](https://devoria.fr/zh-hant/blog/itms-90683-missing-purpose-string-expo) 和 [ITMS-90725](https://devoria.fr/zh-hant/blog/itms-90725-sdk-version-issue-expo)。

2026 年 9 月底，Solys 的一個 build 在交付時因 ITMS-90683 被拒。我整理設定檔時刪掉了一句照片權限說明。Solys 根本沒用到照片，但專案裡有個函式庫會呼叫 iOS 的 Photos API。**Apple 分析的是二進位檔，不是實際用途：**從那之後，我再也不刪這些說明文字了。

至於 Missing Compliance 狀態，它不是上傳錯誤。它代表缺少你的加密聲明，說明請見 [EAS 發布指南](https://devoria.fr/zh-hant/blog/eas-submit-ios-expo-app-store)。

## 我每次上傳前的檢查清單

- `ascAppId` 已寫在 `submit` 設定檔裡，而且是在 build 之前加的。
- API 金鑰由 EAS 管理，或它的三個欄位指向放在儲存庫以外的 `.p8`。
- Account Holder 已在 App Store Connect 同意最新合約。
- 已啟用 `autoIncrement`，搭配 `"appVersionSource": "remote"`，這是 EAS CLI 12 起 [Expo 推薦的做法](https://docs.expo.dev/build-reference/app-versions/)。
- `version` 高於最後一個已核准的版本。
- 二進位檔裡每個敏感 API 都有對應的權限說明文字。
- 新 app 在第一次上傳前，已填好 `appName` 和 `language`。

## 順利送出你的第一個 app

這個指令只是其中一步。[iOS & Android Kit](https://devoria.fr/zh-hant/kits/ios) 以我自己 app 的 Starter Code 為基礎，包含訂閱功能，分四個步驟帶你一路到 App Store，照你自己的節奏來。

如果你正在準備第一次上架，[來做免費診斷](https://devoria.fr/zh-hant/diagnostic)：它會告訴你真正卡住你的是什麼，並寄給你我的 Apple 防退件檢查清單。關於 app 頁面、截圖與審核，[在 App Store 上架 app](https://devoria.fr/zh-hant/expertise/publish-app-on-app-store) 這頁會逐步說明每個步驟。

## 常見問題

### 為什麼 eas submit 只在 CI 裡失敗？

在 `--non-interactive` 模式下，指令沒辦法問你任何問題。它需要設定檔裡的 `ascAppId`，以及一把已綁定 app 的 API 金鑰，或是 `eas.json` 裡的三個金鑰欄位。在你自己的電腦上，它會直接問你這些問題。

### eas submit 出錯後需要重新 build 嗎？

只有在 Apple 以 ITMS 代碼拒收二進位檔時才需要。例外：ITMS-90054 和 90055 代表 build 指向了錯誤的 app 頁面，只要重新上傳到正確的頁面就好。設定與帳號錯誤可以在 `eas.json`、App Store Connect 或你的 Apple 帳號裡修正。然後重新上傳同一個 build，例如用 `--latest` 或 `--id`。

### 在哪裡看 EAS Submit 上傳的日誌？

在 Expo 儀表板裡該次提交的頁面。Expo 建議在那裡讀日誌和「Build Annotations」提示框。在終端機裡，加上 `--verbose` 就會一律顯示日誌。

### 可以用免費 Apple 帳號使用 eas submit 嗎？

不行。Expo 要求付費的 Apple Developer 帳號才能把 app 上傳到 App Store。免費帳號只能在你自己的 iPhone 上測試，不能使用 App Store Connect。

### eas submit 的 API 金鑰要給什麼角色？

Expo 的指南給金鑰 Admin 角色。根據 Apple 的角色表，App Manager 和 Developer 角色也能上傳 build。我的 Expo build 用的是 App Manager 角色的團隊金鑰。只有 Account Holder 和 Admin 能產生團隊金鑰。

### EAS 裡的「Increment Build Number」是什麼意思？

Apple 以 ITMS-90189 代碼拒收了 build：這個版本已經有相同的 build 編號。在 `eas.json` 啟用 `"autoIncrement": true`，或提高 `ios.buildNumber`，然後重新 build。


## 你的專案

[Review Kit](https://devoria.fr/zh-hant/kits/app-review)：我的 App Store 審查檢查清單、我被 Apple 退件後的修正、Google Play 檢查清單，以及三個 Claude Code skill。$1,749。

[iOS & Android Kit](https://devoria.fr/zh-hant/kits/ios)：用 Claude Code 打造你的 iPhone 和 Android App：我自己 App 的起始程式碼、上架商店的完整流程，以及所有套件。$3,599。

[診斷：你離自己的 iPhone App 還差什麼](https://devoria.fr/zh-hant/diagnostic)：7 個問題，60 秒：找出真正卡住你發布 iPhone App 的原因，拿到你的 4 步驟路線，以及最適合你的套件。
