Skip to content

iOS build errorXcode: “Command PhaseScriptExecution failed with a nonzero exit code”

An iOS build fails with Command PhaseScriptExecution failed with a nonzero exit code. That line only says one of the target’s Run Script build phases failed; the real error is printed just above it. In Flutter and React Native apps the script is usually the one that builds the Dart or JavaScript bundle, or a CocoaPods script.

Short answer

Open the Report navigator (the last tab in the left sidebar), select the failed build and expand the failing script step to read its own error. Then fix that: a line like “Sandbox: rsync.samba(...) deny(1) file-write-create” means user script sandboxing (Build Settings, Build Options, User Script Sandboxing: No for the app target); “node: command not found” in React Native means Xcode can’t find Node (set NODE_BINARY in ios/.xcode.env.local); “The sandbox is not in sync with the Podfile.lock” means run pod install.

Which script failed, and the fix

  1. 01

    Read the script’s own error first

    The summary hides the cause. In the Report navigator, open the latest build, find the red Run custom shell script step, and expand it with the button on the right of the line. The last lines before “exit code” name the real problem.

  2. 02

    User script sandboxing (Xcode 15 and later)

    “If enabled, the build system will sandbox user scripts to disallow undeclared input/output dependencies.” Apple Developer, Build settings reference: User Script Sandboxing

    New projects and upgraded ones can have user script sandboxing on, so scripts that read or write files they have not declared fail with a line like Sandbox: rsync.samba(12345) deny(1) file-write-create, or Operation not permitted. CocoaPods’ embed frameworks script is a common victim. Set Build Settings, Build Options, User Script Sandboxing to No for the app target, or declare the script’s input and output files.

    // Build Settings of the app target
    ENABLE_USER_SCRIPT_SANDBOXING = NO
  3. 03

    React Native: Xcode can’t find Node

    The Bundle React Native code and images phase runs Node, but Xcode does not load your shell profile, so Node installed with nvm, fnm or Volta is not on its PATH. On React Native 0.69 and later, point the build at it in ios/.xcode.env.local; on older versions, set the Node path in that build phase’s script. Firebase Crashlytics’ upload-symbols script fails the same way when its path is wrong after a pod update.

    # ios/.xcode.env.local
    export NODE_BINARY=$(command -v node)
  4. 04

    CocoaPods or Flutter scripts out of date

    “The sandbox is not in sync with the Podfile.lock” comes from the Check Pods Manifest.lock phase: run pod install. In Flutter, a failing Run Script phase often means the Flutter build itself failed: run flutter build ios in a terminal to see the Dart error, and run flutter clean and flutter pub get if generated files are stale.

    flutter clean && flutter pub get
    cd ios && pod install && cd ..
    flutter build ios

Checked against the vendor’s docs on : Apple Developer: Build settings reference (User Script Sandboxing).

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Xcode “No such module” · Flutter “pod install” failed · React Native “Unable to load script” · Xcode provisioning profile invalid or expired

Questions

More on this error

Is it safe to turn off user script sandboxing?

For most app targets, yes: it is how projects built before Xcode 15 worked. The safer long-term fix is to declare each script’s input and output files, so Xcode can sandbox it and skip it when nothing changed.

It builds in Xcode but fails on CI or Xcode Cloud. Why?

The CI machine has a different Node, Ruby, CocoaPods or Flutter version, or missing environment files. Print the versions in the CI log and install the same ones as on your machine.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.