iOS打包报错Command PhaseScriptExecution失败,疑似expo-updates问题
我尝试通过Xcode构建React Native iOS应用,该项目最初在Windows电脑上使用Expo托管工作流开发。由于应用仅供公司内部支持人员使用,无需发布至App Store,因此我将项目转为裸工作流以制作无需ExpoGo的独立安装包。在MacBook上完成Brew、NPM、Pods、Watchman等环境配置后,构建时出现以下错误:
PhaseScriptExecution [CP-User]\ Generate\ app.manifest\ for\ expo-updates /Users/myusername/Library/Developer/Xcode/DerivedData/myAppName-bfzizgdigfiavjaaxczcpfyuwfnp/Build/Intermediates.noindex/Pods.build/Release-iphoneos/EXUpdates.build/Script-46EB2E00013D80.sh (in target 'EXUpdates' from project 'Pods') /Xcode/DerivedData/myAppName-bfzizgdigfiavjaaxczcpfyuwfnp/Build/Intermediates.noindex/Pods.build/Release-iphoneos/EXUpdates.build/Script-46EB2E00013D80.sh Node found at: /usr/local/bin/node Welcome to Metro! Fast - Scalable - Integrated node:events:491 throw er; // Unhandled 'error' event ^ Error: EMFILE: too many open files, watch at FSEvent.FSWatcher._handle.onchange (node:internal/fs/watchers:204:21) Emitted 'error' event on NodeWatcher instance at: at NodeWatcher.checkedEmitError (/Users/myusername/Develop/projectFolder/ProjectSubFolder/react-apps/myAppname/node_modules/jest-haste-map/build/watchers/NodeWatcher.js:141:12) at FSWatcher.emit (node:events:513:28) at FSEvent.FSWatcher._handle.onchange (node:internal/fs/watchers:210:12) { errno: -24, syscall: 'watch', code: 'EMFILE', filename: null } Command PhaseScriptExecution failed with a nonzero exit code Node found at: /usr/local/bin/node Welcome to Metro! Fast - Scalable - Integrated node:events:491 throw er; // Unhandled 'error' event ^ Error: EMFILE: too many open files, watch at FSEvent.FSWatcher._handle.onchange (node:internal/fs/watchers:204:21) Emitted 'error' event on NodeWatcher instance at: at NodeWatcher.checkedEmitError (/Users/myusername/Develop/projectFolder/ProjectSubFolder/react-apps/myAppname/node_modules/jest-haste-map/build/watchers/NodeWatcher.js:141:12) at FSWatcher.emit (node:events:513:28) at FSEvent.FSWatcher._handle.onchange (node:internal/fs/watchers:210:12) { errno: -24, syscall: 'watch', code: 'EMFILE', filename: null } Command PhaseScriptExecution failed with a nonzero exit code
环境信息
- MacBook Air M1
- Xcode 14.1
- macOS Monterey v12.5
- NPM 8.19.2
- Node v16.18.1
- Homebrew 3.6.12
- Watchman 2022.11.14.00
已尝试的解决方案
- 执行
pod deintegrate和pod install - 重新安装Watchman无效
- 将Node从v18降级至v16
- 删除node_modules后重新执行
npm install - 执行Brew cleanup
- 锁定并解锁钥匙串
- 清理Xcode项目
- 使用arch -x86_64执行
pod deintegrate和pod install - 通过x86_64架构的Homebrew安装watchman
- 在Rosetta终端运行Metro服务器
- 不使用Rosetta运行XCode
- 执行命令:
sudo launchctl limit maxfiles 16384 16384 && ulimit -n 16384
特殊尝试后的崩溃问题
在Pods目标的**[CP-User] Generate app.manifest for expo-updates**部分勾选"Run script only when installing"后,应用可成功构建并安装到iPhone,但打开时显示启动页后崩溃,Xcode抛出以下错误:
libc++abi: terminating with uncaught exception of type NSException terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The embedded manifest is invalid or could not be read. Make sure you have configured expo-updates correctly in your Xcode Build Phases.
我已为此问题困扰近一周,尝试了各种方法均无效,尚未尝试的最后方案是新建裸项目并迁移代码,但希望能修复当前项目。请问是否有遗漏的expo-updates配置问题?还有其他解决办法吗?
针对EMFILE文件句柄不足的问题
永久调整系统文件句柄限制
临时命令重启后会失效,需写入系统配置永久生效:- 创建或编辑
/Library/LaunchDaemons/limit.maxfiles.plist文件,内容如下:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>limit.maxfiles</string> <key>ProgramArguments</key> <array> <string>launchctl</string> <string>limit</string> <string>maxfiles</string> <string>65536</string> <string>200000</string> </array> <key>RunAtLoad</key> <true/> <key>ServiceIPC</key> <false/> </dict> </plist> - 执行以下命令加载配置并重启Mac:
sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist
重启后验证:
launchctl limit maxfiles,确认数值已更新。- 创建或编辑
强制Metro使用Watchman监控文件
确保项目根目录的metro.config.js开启Watchman支持:const { getDefaultConfig } = require('expo/metro-config'); const config = getDefaultConfig(__dirname); config.watchFolders = [__dirname]; config.resolver.useWatchman = true; module.exports = config;检查Watchman监控状态:
watchman watch-list,若项目目录不在列表中,执行watchman watch-project /path/to/your/project手动添加。
针对expo-updates的Manifest无效问题
勾选"Run script only when installing"会导致manifest未在每次构建时生成,这是崩溃的核心原因,按以下步骤修复:
- 恢复脚本默认运行设置
取消勾选"Run script only when installing",先解决EMFILE问题再重新构建。 - 手动预生成manifest
构建前手动执行命令生成manifest:
将生成的npx expo export --platform ios --output-dir ios/buildapp.manifest复制到ios/Pods/EXUpdates/目录后,再尝试Xcode构建。 - 检查expo-updates配置
- 确认
app.json/app.config.js中更新配置正确:"updates": { "enabled": true, "fallbackToCacheTimeout": 0, "checkAutomatically": "ON_LOAD" } - 检查Xcode中
EXUpdates目标的Build Phases,确认[CP-User] Generate app.manifest for expo-updates脚本路径和参数无误,脚本应包含调用npx expo-updates export-manifest的逻辑。
- 确认
- 重置expo-updates状态
执行以下命令清除缓存并重新配置:npx expo-updates clean npx pod-install ios
其他备选方案
- 禁用expo-updates(内部使用场景适用)
若无需更新功能,可直接禁用:- 在
app.json中设置"updates": { "enabled": false } - 移除Xcode中
EXUpdates相关的Build Phases脚本 - 执行
pod deintegrate && pod install重新安装依赖
- 在
- 清理项目目录
Windows转Mac的项目可能存在冗余隐藏文件,执行命令清理:
同时尽量缩短项目路径层级,减少文件监控压力。find . -name ".DS_Store" -delete
内容的提问来源于stack exchange,提问作者Nox

