Few things break the flow of mobile development like an Xcode update. One morning your Flutter build works perfectly; the next, after an innocuous update to Xcode 14 or 15, you are greeted with a build failure.
The console spews a wall of text ending in Command PhaseScript Execution failed, but the smoking gun is buried deeper in the logs:
sandbox: rsync.samba(13105) deny(1) file-write-create /Users/username/Library/Developer/Xcode/DerivedData/...
If you are seeing rsync.samba deny or generic PhaseScript failures during the "Embed Pods Frameworks" or "Thin Binary" phases, you have collided with Apple’s tightened build system security.
Here is the root cause analysis and the programmatic fix to resolve this permanently in your Podfile.
The Root Cause: User Script Sandboxing
The error is not a Flutter bug, nor is it strictly a CocoaPods bug. It is a conflict between legacy build script behaviors and modern Xcode security policies.
In recent versions, Xcode enabled User Script Sandboxing by default. This security feature creates a containerized environment for Shell Script Build Phases. Inside this sandbox:
- Scripts can only read files explicitly listed in the "Input Files" list.
- Scripts can only write to files explicitly listed in the "Output Files" list.
- Access to the rest of the filesystem is strictly blocked by the kernel.
The Conflict: Flutter and CocoaPods rely heavily on shell scripts (specifically rsync) to move frameworks, assets, and dSYMs from your cached repositories into the final App Bundle. However, CocoaPods generated scripts often lack the precise Input/Output file lists required to satisfy the sandbox, or they attempt to modify files in intermediate directories that the sandbox does not authorize.
When rsync attempts to write the framework to the build directory, the OS sandbox daemon (sandboxd) intercepts the system call and denies it, triggering the rsync.samba deny error.
The Solution
While you can manually change build settings in Xcode, that solution is brittle. Running pod install will regenerate your project files and wipe out your manual changes.
The robust solution is to use a post_install hook in your ios/Podfile. This ensures the fix is applied automatically every time dependencies are installed or updated.
Step 1: Open your Podfile
Navigate to your Flutter project's iOS directory and open the Podfile.
code ios/Podfile
Step 2: Implement the Sandbox Override
Locate the post_install block. If you don't have one, create it. Add the configuration to explicitly disable User Script Sandboxing for your Pod targets.
Update your Podfile with the following Ruby code:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# ----------------------------------------------------------
# FIX: Disable User Script Sandboxing to resolve rsync errors
# ----------------------------------------------------------
# CocoaPods embed-frameworks scripts are not fully sandbox-compliant.
# This allows rsync to write to the derived data directory without
# kernel denial.
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
# Recommended: Ensure correct archs for iOS simulators on Apple Silicon
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
end
Step 3: Clean and Rebuild
Apply the changes and clean the build artifacts to ensure the new build settings take effect.
cd ios
rm -rf Pods
rm Podfile.lock
pod install
cd ..
flutter clean
flutter pub get
Now, run your build:
flutter run
Why This Fix Works
By setting ENABLE_USER_SCRIPT_SANDBOXING = NO, we are instructing the Xcode Build System to run the shell scripts associated with our Pods in the legacy mode (unsandboxed).
While Apple's long-term goal is for every script to define perfect Input/Output file lists (xcfilelists), the ecosystem—specifically the dynamic nature of CocoaPods and Flutter integration—has not fully caught up.
- Iterating Targets: The
installer.pods_project.targets.eachloop ensures we touch every third-party dependency (e.g.,url_launcher,firebase_core) and the aggregate Pods target. - Modifying Build Settings: We inject the setting directly into the
project.pbxprojstructure via Ruby. This is functionally equivalent to going into Xcode > Build Settings and changing the flag, but it persists acrosspod installexecutions.
Summary
The rsync.samba deny error is a permissions mismatch caused by Xcode's evolution toward hermetic builds. Until the entire Flutter and CocoaPods ecosystem migrates to fully defined xcfilelists, disabling script sandboxing for Pod targets is the standard, reliable engineering solution to keep your CI/CD pipelines and local builds green.