"Command PhaseScriptExecution failed with a nonzero exit code" is a generic Xcode error that means a Run Script build phase failed, not a specific problem on its own. The real cause is in that script's output, so the first move is always to read the actual error, not the headline. In a React Native project, the most common cause is Xcode being unable to find your node binary, which you fix by setting NODE_BINARY in ios/.xcode.env.local. Other frequent causes are missing node_modules, stale CocoaPods or DerivedData, and low disk space.
Short answer
The headline error is generic; the real one is in the failed script's log. Expand the failed phase in Xcode's report navigator to see it, as community writeups like this PhaseScriptExecution guide show. In React Native, the usual cause is Xcode not finding node, especially with a version manager like nvm; fix it by exporting NODE_BINARY in ios/.xcode.env.local, pointing to your node path. If that is not it, reinstall your JavaScript dependencies, run pod install, and clean the build folder and DerivedData. A related class of failures around FBReactNativeSpec and generated scripts is discussed in the React Native issue tracker. Read the real error first, then fix the specific cause.
What "Command PhaseScriptExecution failed" means
Command PhaseScriptExecution failed means that one of the Run Script phases in your Xcode build ran and exited with an error. Xcode reports the phase failed, but the message itself does not say why, because the actual error is whatever the script printed before it exited. It is a wrapper around a real failure, not the failure itself.
This matters because the fix depends entirely on which script failed and why. In a React Native app the failing phase is often the one that bundles your JavaScript, but it could be a CocoaPods phase or a custom script. Treating the headline as the problem leads to guessing; treating it as a pointer to the real log is what gets you to the actual cause quickly.
Read the real error first
Before changing anything, open the real error. In Xcode, go to the report navigator, find the failed build, and expand the failed Run Script phase to see its full output. That output contains the genuine message, such as node not being found, a JavaScript bundling error, or a missing file, which is what you actually need to fix.
This one habit saves the most time. Because PhaseScriptExecution is generic, two builds can show the same headline for completely different reasons, and only the script log tells them apart. If you take one thing from this, make it reading the expanded log first, because every fix below depends on knowing which specific error you have.
Cause 1: Xcode can't find node
The most common React Native cause is that Xcode cannot find your node binary. Xcode runs its build scripts in a limited environment that does not always include the PATH from your shell, so if you use a version manager like nvm, node is not where Xcode expects. The bundling script then fails with a node-not-found error.
The fix is to tell Xcode where node is. Create or edit ios/.xcode.env.local and export NODE_BINARY with the full path to your node, for example the path that the which node command prints. React Native reads this file to locate node during the build, so setting it resolves the most frequent version of this error. Keep .xcode.env.local out of source control, since the path is specific to your machine, and use the committed .xcode.env for shared defaults.
Cause 2: missing node_modules or dependencies
If node is found but the script still fails, the next suspect is missing or broken JavaScript dependencies. If node_modules is absent, incomplete, or out of sync with your lockfile, the bundling phase cannot find the packages it needs and exits with an error. This is common after cloning a project, switching branches, or a partial install.
The fix is to reinstall cleanly. Run your package manager's install, npm install or yarn install, from the project root, and if problems persist, delete node_modules while keeping the lockfile intact and reinstall from scratch. A fresh, complete node_modules that matches your lockfile removes this cause, and it is worth doing early because it is quick and rules out a whole category of failures.
Cause 3: stale pods, DerivedData, or cache
A third common cause is stale native state, especially after you change dependencies. CocoaPods that are out of sync with your Podfile, or a stale DerivedData folder, can make a script phase fail even when your code is fine. This often appears right after adding or updating a library.
The table below maps the common causes to their fixes.
| Cause | Typical sign in the log | Fix |
|---|---|---|
| Node not found | node: command not found, or a bad path | Set NODE_BINARY in ios/.xcode.env.local |
| Missing node_modules | Cannot find module, or bundling errors | Run npm install or yarn install |
| Stale pods or cache | Errors after a dependency change | Run pod install, clean build, clear DerivedData |
| JavaScript bundling error | An error from the bundle script itself | Fix the JS error named in the log |
| Disk space or permissions | I/O or permission-denied errors | Free space, fix file permissions |
Clearing stale state is straightforward: run pod install in the ios folder, use Product then Clean Build Folder in Xcode, and delete the DerivedData folder for the project. Then rebuild. This resets the native side to a clean, consistent state that matches your current dependencies.
The safe fix sequence
Rather than trying fixes at random, work them in order from cheapest to most involved. The checklist below is a reliable sequence for a React Native PhaseScriptExecution failure.
| Step | Action | Why |
|---|---|---|
| 1 | Expand the failed phase in the report navigator | Find the real error |
| 2 | Set NODE_BINARY in ios/.xcode.env.local | The most common cause |
| 3 | Reinstall JS deps with npm or yarn install | Restores node_modules |
| 4 | Run pod install in the ios folder | Syncs native dependencies |
| 5 | Clean the build folder and delete DerivedData | Clears stale state |
| 6 | Rebuild and check the log again | Confirms the fix or narrows it |
The order matters because the early steps are quick and cover the most frequent causes, so you often stop after step two or three. If you still fail after the full sequence, the expanded log from step one will now show a more specific error to chase, rather than the generic headline.
Other causes: disk space, permissions, and specific pod phases
Some failures are environmental rather than about React Native itself. A full disk can make a script fail partway through with an input or output error, and file-permission problems can stop a script from writing where it needs to. Both show up as a nonzero exit but have nothing to do with your code, so check free space and permissions when the log points that way.
It can also be a specific CocoaPods phase, shown as a bracketed name like a [CP] script, rather than the React Native bundling phase. When that is the failing phase, the fix lives with that pod or with your Pods setup, so read which phase failed. The generic headline hides this, which is one more reason the expanded log is the starting point every time.
Preventing it in CI
The same error often appears in CI or on a teammate's machine even when it builds for you, because their environment differs. The usual culprit is again node: a CI runner may have node at a different path, or none on the PATH Xcode sees. Pinning the node location, via a committed .xcode.env with a sensible default and ensuring node is installed on the runner, prevents most of these.
Make the build reproducible rather than machine-specific. Commit lockfiles, run a clean install in CI, and do not depend on paths that only exist on one developer's laptop. A build that assumes your local setup is one that fails the moment it runs anywhere else, and this error is a frequent symptom of that assumption.
After it builds, scan before you ship
Getting the build to succeed is the goal here, but a successful build is not automatically one you should ship. The build process does not inspect your app for security problems, so a React Native build that finally compiles can still carry an embedded API key in the bundle, allow cleartext traffic, or leave a debuggable flag on.
A scanner like PTKD.com analyzes your .ipa or .apk and returns findings ordered by severity and mapped to OWASP MASVS, so once the build works you can check it for embedded secrets and insecure configurations before release. To be clear about the boundary: PTKD does not fix a PhaseScriptExecution error or your Xcode build, and it does not manage your node setup. It checks the artifact the build produces, which is where a security issue actually reaches users.
What to take away
- Command PhaseScriptExecution failed is a generic wrapper; the real error is in the failed script's output, so read that first.
- The most common React Native cause is Xcode not finding node; set NODE_BINARY in ios/.xcode.env.local.
- Reinstall node_modules, run pod install, and clear DerivedData to rule out missing dependencies and stale state.
- Work the fixes in order and check which phase failed, since a CocoaPods phase points at a different fix.
- After the build succeeds, scan it with PTKD.com, because a build that compiles is not automatically secure.




