eas submit iOS 常见错误及解决方法
作者:Mehdi Azizi
发布于 ,10分钟
eas submit 失败?逐条解析 EAS 和 App Store Connect 的真实报错、原因与修复:ascAppId、API 密钥、Apple 协议、ITMS 代码。
当 eas submit --platform ios 失败时,报错信息几乎总会告诉你该看哪里。要么是你的 EAS 配置不完整,要么是你的 Apple 账号卡住了,要么是 Apple 拒绝了二进制文件。前两种情况几分钟就能修好,不需要重新构建。第三种能从 ITMS 代码认出来,而且几乎总是需要重新构建。
我用 Expo 和 EAS 发布自己的 iOS 应用,包括 Solys、TradaZen 和 Nolera。这里引用的报错信息都摘自 EAS CLI 的源代码,来自 Expo 官方 GitHub 仓库,我在 2026 年 11 月 3 日重新核对过。Expo 的旧论坛现在已经转向 Discord:代码仍然是最可靠的来源。如果你想看完整流程,从 eas.json 文件一直到提交审核,请先读 EAS Submit iOS:把 Expo 应用发布到 App Store。这篇只讲修复。
eas submit 做什么,需要什么
根据 Expo 文档,这条命令会把你的 .ipa 文件发送到 App Store Connect。Apple 处理完之后,构建会出现在 TestFlight 里,一般需要 10 到 15 分钟。它不会把你的应用提交审核:这一步仍然要你在 App Store Connect 里手动完成。
Expo 关于 iOS 提交的页面列出了三个前提条件:
- 付费的 Apple Developer 账号,任何提交到 App Store 的操作都需要它;
- bundle identifier,写在
ios.bundleIdentifier里; - 已安装 EAS CLI,并登录你的 Expo 账号。
如果要在无交互模式下提交,同一页面还要求两项设置:
eas.json的submit配置中的ascAppId,也就是你在 App Store Connect 中应用页面的编号;- 一个 App Store Connect API 密钥,可以由 EAS 管理,也可以你自己提供。它的创建、权限角色和撤销方法,详见 App Store Connect API 密钥(.p8)。
最小配置只需要几行。这里的值是虚构的:
{
"submit": {
"production": {
"ios": {
"ascAppId": "1234567890"
}
}
}
}
如果 EAS 已经保存了你的 API 密钥,这个配置就够了。我的大部分应用都是这样。
看懂报错:三类错误
在找修复方法之前,先确认命令是在哪个阶段停下的。下面这张表是我每次失败时都会对照的。
| 失败阶段 | 类别 | 需要重新构建? |
|---|---|---|
| 发送任何内容之前 | EAS 配置 | 否 |
| 连接 Apple、创建应用记录 | Apple 账号 | 否 |
| 发送之后,出现 ITMS-90xxx 代码 | 二进制被拒 | 几乎总是 |
详细信息可以在 Expo 控制台中该次提交的页面上查看。Expo 建议在那里阅读日志,并留意“Build Annotations”提示框,它会标出常见的失败原因。在终端里,根据 EAS CLI 参考文档,加上 --verbose 选项就会始终显示 EAS Submit 的日志。
EAS 配置错误
“Set ascAppId in the submit profile (eas.json) or re-run this command in interactive mode.”
你用 --non-interactive 运行了命令(比如在持续集成中),而你的配置里没有 ascAppId。这时 EAS CLI 的代码会直接停止:它既不能向你提问,也不能替你创建应用记录。
修复方法:把应用记录的编号填进 ascAppId。Expo 说明了在哪里找到它:在 App Store Connect 中打开你的应用,然后进入 App Information。它就是 General Information 下的 Apple ID 字段,一个十位左右的数字。它既不是你的 Apple 邮箱地址,也不是你的 bundle identifier。
在 Nolera 上,没有 ascAppId 时,命令会要求我登录一个会过期的 Apple Developer 会话。自从把编号写进 eas.json,提交时就什么都不用再问了。
在构建之前添加
ascAppId,不要在构建之后。直到 SDK 57,Expo 计算的指纹都会包含eas.json。在 Vigie 上,运行时版本采用fingerprint策略,我在构建之后才加上这个编号,结果指纹变了:之后发布的更新永远不会到达已安装的那个构建。根据 Expo 的版本更新日志,从 SDK 58 起,指纹的默认预设balanced会忽略eas.json。
“App Store Connect API Keys cannot be set up in --non-interactive mode.”
你的配置里没有密钥,EAS 也没有为你的应用关联任何密钥。Expo 明确说明:在无交互模式下,命令无法向你索取密钥,于是会带着这条信息失败。
有两种修复方法:
- 让 EAS 创建并保存密钥。在你自己的电脑上,以交互模式运行一次
eas credentials --platform ios,让它为你的应用配置一个 App Store Connect API 密钥。 - 使用你自己的密钥,填在
ascApiKeyPath、ascApiKeyIssuerId和ascApiKeyId里。根据 eas.json 参考文档,这三个字段都支持环境变量,比如$ASC_API_KEY_PATH。
在我最新的一个应用上,--auto-submit 选项想要一个 Apple 账号来创建它的提交密钥。我把自己密钥的三个字段写进了本地工作副本的配置里,从不提交到仓库。然后我用 --id 和 --non-interactive 发送了已经完成的构建。
“EXPO_APPLE_APP_SPECIFIC_PASSWORD must be in the format xxxx-xxxx-xxxx-xxxx, where x is a lowercase letter.”
这个变量里放的不是 App 专用密码,常常是你的 Apple 账号密码本身。EAS CLI 会在发送任何内容之前检查这个格式。
根据 Apple 帮助文档,App 专用密码在 account.apple.com 的 App-Specific Passwords 栏目中生成,前提是开启了双重认证。一旦你修改 Apple 账号密码,它就会被撤销。Expo 认为这种方式不如 API 密钥安全,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 的角色权限表,只有账号持有人(Account Holder)才能接受协议。EAS 的代码会提示他前往 App Store Connect 的 Business 页面,如果 Apple 有提示,再去 developer.apple.com 上的账号页面处理。然后重新运行命令。付费应用协议有专门的指南:App Store Connect 中的 Paid Apps Agreement。
“App Store Connect rejected the API authentication credentials.”
Apple 返回了 401 错误,NOT_AUTHORIZED。EAS 列出了三个原因:密钥已失效,密钥属于另一个 App Store Connect 账号,或者 Key ID、密钥内容、Issuer ID 有误。
在 App Store Connect 的 Users and Access 菜单、Integrations 标签页里核对这两个标识符。根据 Apple,Issuer ID 显示在页面顶部,Key ID 显示在有效密钥列表里。被撤销的密钥永远无法重新启用。Apple 会在 Revoked 下显示它 30 天:你必须生成一个新的。
“App Store Connect app for application identifier … was not found.”
用你的密钥找不到 ascAppId 指向的应用记录。EAS 会让你检查这个编号,并确认该密钥在正确的账号中确实能访问这个应用。它甚至会列出这个密钥能看到的几个应用。如果用 Apple 自己的上传工具,同样的问题会显示为“No suitable application records were found”。
常见原因有三个,其中两个出自 Apple 论坛的这个帖子:
- 应用记录不存在。在 App Store Connect 中创建它,或者去掉
ascAppId,让命令自动创建。 - 编号来自另一个账号。你复制了另一个团队或另一个项目的
ascAppId。 - 用户没有该应用的访问权限。App Manager 或 Developer 可能被限制只能访问部分应用。而团队密钥则可以访问账号下的所有应用。
“… is not available to team”或“… is not available to provider”
这条信息出现在缺少 ascAppId、由 EAS 替你创建应用记录的时候。这个 bundle identifier 已经被另一个团队占用了。EAS 会让你在应用配置中修改它,然后重新运行。
“App name "…" is already taken. Using generated name "…"”
这不是失败。当名称在 App Store 上已被占用时,EAS 会随机加上六个字符重试,最多五次。之后你可以在 App Store Connect 里给应用记录改名。想避免这种情况,在首次提交前就在配置中填好 appName 和 language:如果没有 language,主语言默认是 en-US。
二进制错误:ITMS 代码
发送之后,Apple 会处理构建。如果被拒,日志里会出现一个或多个 ITMS 代码。下面是 EAS 提交步骤能识别并解释的代码:
| ITMS 代码 | Apple 拒绝的原因 | 修复方法 |
|---|---|---|
| 90189 | 构建号已被使用 | autoIncrement |
| 90062, 90186, 90478 | 版本已关闭或已被超过 | 提高 version |
| 90683 | 缺少权限说明文字 | ios.infoPlist |
| 90725 | iOS SDK 过旧 | iOS 镜像或 Expo SDK |
| 90054, 90055 | bundle 与目标应用记录不一致 | 修正 ascAppId |
| 90022, 90023, 90391, 90713 | 图标缺失或声明错误 | 检查图标 |
| 90771 | 缺少后台任务标识符 | ios.infoPlist |
从这些信息中可以得出三点:
- 每个版本的构建号必须唯一。针对 90189,EAS 建议在
eas.json中设置"autoIncrement": true。详见 构建号与版本号。 - 针对 90725,EAS 建议在
eas.json中选择更新的 iOS 镜像,必要时升级到受支持的 Expo SDK。 - 针对 90771,你的 Info.plist 声明了
processing后台模式,却没有声明BGTaskSchedulerPermittedIdentifiers键。
除了 90054 和 90055(只需指向正确的应用记录或换一个构建),修复都涉及二进制文件:重新构建,然后再次提交。有两个代码有专门的指南:Expo 下的 ITMS-90683 和 ITMS-90725。
2026 年 9 月底,Solys 的一个构建在交付时因 ITMS-90683 被拒。我在清理配置文件时删掉了一条关于照片的权限说明。Solys 并不使用照片,但项目里的某个库调用了 iOS 的 Photos API。Apple 分析的是二进制文件,而不是实际用途:从那以后,我再也不删这些说明文字了。
至于 Missing Compliance 状态,它并不是提交错误。它表示缺少你的加密声明,具体见 EAS 发布指南。
我每次提交前的检查清单
ascAppId已写在submit配置中,并且是在构建之前加的。- API 密钥由 EAS 管理,或者它的三个字段指向存放在仓库之外的
.p8文件。 - Account Holder 已在 App Store Connect 中接受最新的协议。
autoIncrement已开启,并配合"appVersionSource": "remote",这是 EAS CLI 12 起 Expo 推荐的做法。version高于最近一个已获批准的版本。- 二进制中出现的每个敏感 API 都有对应的权限说明文字。
- 对于新应用,首次提交前已填好
appName和language。
顺利提交你的第一个应用
这条命令只是其中一步。iOS & Android Kit 以我自己应用的 Starter Code 为基础(包含订阅功能),带你按自己的节奏走完通往 App Store 的四个步骤。
如果你正在准备第一次上架,来做免费诊断:它会告诉你真正卡住你的是什么,并把我的 Apple 防拒审清单发给你。关于应用页面、截图和审核,把应用发布到 App Store 这一页逐步讲解了每个环节。
常见问题
为什么 eas submit 只在持续集成中失败?
在 --non-interactive 模式下,命令无法向你提问。它需要配置中的 ascAppId,以及一个已经关联到该应用的 API 密钥,或者在 eas.json 中填好密钥的三个字段。在你自己的电脑上,它本来会问你这些问题。
eas submit 出错后需要重新构建吗?
只有当 Apple 以 ITMS 代码拒绝二进制文件时才需要。例外:ITMS-90054 和 90055 表示构建指向了错误的应用记录,只需把它重新发送到正确的记录。配置错误和账号错误可以在 eas.json、App Store Connect 或你的 Apple 账号中修复。然后重新发送同一个构建,比如用 --latest 或 --id。
在哪里查看 EAS Submit 的提交日志?
在 Expo 控制台中该次提交的页面上。Expo 建议在那里阅读日志和“Build Annotations”提示框。在终端里,加上 --verbose 就会始终显示日志。
免费的 Apple 账号能用 eas submit 吗?
不能。Expo 要求使用付费的 Apple Developer 账号才能把应用提交到 App Store。免费账号可以在你自己的 iPhone 上测试,但不能使用 App Store Connect。
eas submit 用的 API 密钥应该给什么角色?
Expo 的指南给密钥分配的是 Admin 角色。根据 Apple 的角色权限表,App Manager 和 Developer 角色也可以上传构建。我的 Expo 构建用的是 App Manager 角色的团队密钥。只有 Account Holder 和 Admin 才能生成团队密钥。
EAS 中的“Increment Build Number”是什么意思?
Apple 以 ITMS-90189 代码拒绝了构建:这个构建号在该版本下已经存在。在 eas.json 中开启 "autoIncrement": true,或者提高 ios.buildNumber,然后重新构建。

