UE 5.8.1 iOS Archive fails with "cp: <App>.app: Not a directory" during PhaseScriptExecution on Xcode 26.1.1

Summary

After upgrading to Xcode 26.1.1, Unreal Engine 5.8.1 is unable to archive an iOS project.
The project builds successfully, links successfully, and the application is staged correctly. The failure only occurs during the Xcode Archive phase in the generated “Copy Executable and Staged Data into .app” build script.
The generated script attempts to copy staged files into:
/ArchiveIntermediates//BuildProductsPath/IOS/-IOS-Shipping.app
However, the destination is not treated as a directory and the script fails with:
cp: -IOS-Shipping.app: Not a directory
Command PhaseScriptExecution failed with a nonzero exit code
As a result, Xcode fails to create the .xcarchive and Unreal reports:
Unable to find a .xcarchive in Xcode’s Library
This issue is reproducible after cleaning DerivedData, Intermediate, Binaries and Saved folders.
The project packages correctly up to the staging step. The failure only occurs during the Archive step.

What Type of Bug are you experiencing?

Platform Mobile

Steps to Reproduce

  1. Install Unreal Engine 5.8.1 (Launcher build).
  2. Install Xcode 26.1.1.
  3. Open any iOS project.
  4. Package/Archive for iOS.
  5. Wait until the Archive phase begins.
  6. Observe that the “Copy Executable and Staged Data into .app” PhaseScriptExecution fails.

Expected Result

The generated Xcode project should successfully create an .xcarchive and Unreal should continue packaging normally.

Observed Result

Archive fails during PhaseScriptExecution with:
cp: -IOS-Shipping.app: Not a directory
No .xcarchive is generated.

Affects Versions

5.8

Platform(s)

iOS

2 Likes

Hi there. I would like to +1 on this. Have you found a solution in the meantime?

No, but version 5.8.2 has been released. I checked the release notes and didn’t see anything indicating the issue had been fixed, but I’ll give it another try anyway.

Any solution to this? Thanks in advance!

1 Like

No, I haven’t made any progress yet. How about you?

Hi all. I was able to make some progress on this. By patching an engine file (XcodeProject.cs), then rebuilding the UnrealBuildTool I am now able to create a working .xcarchive via Xcode. But ONLY via Xcode. When I try to create one using the Package Project command from within the editor, then it always produces an old .xcarchive (the last successful one it can find).

So, although I can work with this and at least get my stuff out, it of course isn’t perfect. But someone in the Unreal Slackers Discord mentioned, that it has been working for them with source build versions of the engine.

If anyone is interested I can share more details on how to apply the patch, or you can use a source version of the engine, which should also work. The “fix” is quiet elaborate if one has no clue about the whole Unreal Engine build pipeline (as I myself do not).

Sadly even the 5.8.3 hotfix didn’t resolve this on my end.

Edit: After also rebuilding the AutomationTool it now works across all packaging variants. Package Project from within the editor, using the build command (with -archive) in Terminal and via Xcode - Product - Archive. I will follow up with a write up on how to apply the fix yourself tomorrow.

Hi all. So, here follows the quiet elaborate write up of what I had to do, to get this to work with an UE5.8 binary build of the engine. First and foremost you should be familiar with Terminal on Mac to get through this. I did this on my Mac, therefore the paths are Mac specific, but you should be able to apply this to CMD on Windows as well, at least for the patching part.

Then as a disclaimer: I was able to work around this issue by using Claude Code. So, decide for yourself if you want to trust this or not. I can only affirm you that it has worked for me.

Now let’s get going:

Symptoms

  • Packaging for iOS produces a working .app that installs fine on-device via Xcode, but never produces a valid, submittable .xcarchive
  • Enabling “Generate Xcode Archive” + “For Distribution” in Project Settings doesn’t help
  • Manually forcing -archive -distribution via RunUAT.sh BuildCookRun fails with:
cp: .../BuildProductsPath/IOS/<YourApp>.app: Not a directoryCommand PhaseScriptExecution failed with a nonzero exit code
** ARCHIVE FAILED **
  • If UAT still reports “success” afterward, check the resulting .xcarchive closely — UAT’s archive step silently falls back to copying an old, stale archive from ~/Library/Developer/Xcode/Archives/ when the real xcodebuild archive invocation fails, so it can look deceptively fine at a glance.
  • This happens on Xcode 15+ (confirmed on 16.1 and 26.1), independent of engine hotfix version (reproduced on 5.8.2 and 5.8.3).

Root cause

During an Xcode Archive (“install”) build, Xcode redirects CONFIGURATION_BUILD_DIR through a compatibility symlink pointing to the real product location (InstallationBuildProductsLocation). This is normal Xcode behavior, not an engine bug by itself.

The bug is in the “Copy Executable and Staged Data into .app” script phase that UnrealBuildTool generates for iOS targets. One specific line:

cp -r "${UPL_BUILD_DIR}" "${CONFIGURATION_BUILD_DIR}/${CONTENTS_FOLDER_PATH}"

copies your plugins’ UPL build output (e.g. GoogleService-Info.plist) using cp -r against that symlinked destination. macOS’s cp -R/-r does not treat a symlink-to-directory as a valid “copy into” target the way a plain cp or rsync does, and fails with Not a directory. This never surfaces on a normal device Build (no symlink involved there), only on Archive — which is why it’s so easy to miss.

Fixing XcodeProject.cs

You need to adjust and add some lines of code to the XcodeProject.cs file, which can be found here:

File: Engine/Source/Programs/UnrealBuildTool/ProjectFiles/Xcode/XcodeProject.cs, method ProcessScripts.

  1. Insert a new line right after line 1556 (the rsync that copies the executable), inside the first CopyScript.AddRange block:

"rsync -au \\\"${SRC_EXE}\\\" \\\"${DEST_EXE}\\\"",
Add: "CONTENTS_DIR=$(cd -P \\\"${CONFIGURATION_BUILD_DIR}/${CONTENTS_FOLDER_PATH}\\\" && pwd)",

  1. Line 1638 (Program branch’s rm -rf) — interpolated string, change:

Replace: $" rm -rf \\\"${{CONFIGURATION_BUILD_DIR}}/${{CONTENTS_FOLDER_PATH}}{SyncDestSubdir}\\\"",
With: $" rm -rf \\\"${{CONTENTS_DIR}}{SyncDestSubdir}\\\"",

  1. Line 1663 (the uecommandline.txt copy):

Replace: " cp \\\"${STAGED_DIR}/uecommandline.txt\\\" \\\"${CONFIGURATION_BUILD_DIR}/${CONTENTS_FOLDER_PATH}\\\"",
With: " cp \\\"${STAGED_DIR}/uecommandline.txt\\\" \\\"${CONTENTS_DIR}\\\"",

  1. Line 1667 — this is the actual bug, the cp -r for the UPL build output:

Replace: "cp -r \\\"${UPL_BUILD_DIR}\\\" \\\"${CONFIGURATION_BUILD_DIR}/${CONTENTS_FOLDER_PATH}\\\"",
With: "cp -r \\\"${UPL_BUILD_DIR}\\\" \\\"${CONTENTS_DIR}\\\"",

  1. Line 1677 (the cookeddata rsync) — interpolated string, change:
    Replace: $"rsync -a --delete {ExcludeString} \\\"${{STAGED_DIR}}{SyncSourceSubdir}/\\\" \\\"${{CONFIGURATION_BUILD_DIR}}/${{CONTENTS_FOLDER_PATH}}{SyncDestSubdir}\\\"",
    With: $"rsync -a --delete {ExcludeString} \\\"${{STAGED_DIR}}{SyncSourceSubdir}/\\\" \\\"${{CONTENTS_DIR}}{SyncDestSubdir}\\\"",

Applying the fix

  1. Edit XcodeProject.cs as above.
  2. Rebuild UnrealBuildTool itself — editing the .cs file alone does nothing until it’s recompiled. You can do this via this command in Terminal:
"<EngineDir>/Binaries/ThirdParty/DotNet/<version>/<platform>/dotnet" build \  "<EngineDir>/Source/Programs/UnrealBuildTool/UnrealBuildTool.csproj" -c Development

Then find where it actually built to (it does not land in Engine/Binaries/DotNET/... automatically):

find "<EngineDir>/Source/Programs/UnrealBuildTool" -name "UnrealBuildTool.dll"

and sync the real bin/Development/<tfm>/ output folder into place:

rsync -a "<found bin folder>/" "<EngineDir>/Binaries/DotNET/UnrealBuildTool/"

Essentially we want to copy the newly built DLLs and other files for the UnrealBuildTool from .../UE_5.8/Engine/Source/Programs/UnrealBuildTool/bin/Development/net10.0/... to .../UE_5.8/Engine/Binaries/DotNET/UnrealBuildTool/.... And yes, make sure to override those. You can always use the verify option via the Launcher to revert those, or just copy the directory beforehand as backup.

  1. If you’re on a Launcher/binary-installed engine (not a source build), you must also rebuild AutomationTool — this is the step that’s easy to miss and was quiet a doozy to find out. AutomationTool (which drives RunUAT/BuildCookRun’s -archive step, and is what the Editor’s “Package Project” button uses) ships precompiled and is not automatically rebuilt when you patch UnrealBuildTool. Source builds work “by default” simply because they recompile everything, including AutomationTool, during normal engine setup. Now, we want to actually rebuild AutomationTool the same way we did with UnrealBuild tool. Here are some Terminal commands to do it:
# 1. Find the path for the AutomationTool.csproj
find "<EngineDir>/Source/Programs/AutomationTool" -maxdepth 1 -name "*.csproj""<dotnet path>"

# 2. Rebuild the AutomationTool
build "<AutomationTool.csproj path>" -c Development

# 3. Get the path where the newly built AutomationTool DLL and files are
find "<EngineDir>/Source/Programs/AutomationTool" -name "AutomationTool.dll"

# 4. Copy them to the actual AutomationTool DLL path (binaries)
rsync -a "<found bin folder>/" "<EngineDir>/Binaries/DotNET/AutomationTool/"

So, again: You need to use the first two commands to actually build the AutomationTool. Step 3. & 4. are optional and you can just manually copy those files over if you prefer to do it manually.

These are the paths if you wish to do so: .../UE_5.8/Engine/Source/Programs/AutomationTool/bin/Development/net10.0/... to .../UE_5.8/Engine/Binaries/DotNET/AutomationTool/...

  1. Delete any stale generated project files/caches so everything regenerates from the patched tools:
# 1. Delete ProjectFilesIOS located in your projects intermediate folder
rm -rf "<ProjectDir>/Intermediate/ProjectFiles" "<ProjectDir>/Intermediate/ProjectFilesIOS"

# 2. Delete derived data from your Macs developer folder
rm -rf ~/Library/Developer/Xcode/DerivedData/<YourProject>*
  1. Try packaging again — via Terminal RunUAT.sh BuildCookRun ... -distribution -archive, or the Editor’s “Package Project”, or a manual Xcode Archive. All three now work identically.

Make sure to verify

  • Check the resulting .xcarchive: Products/Applications/<App>.app should be several hundred MB (includes your actual cooked content), not just tens of MB (executable only).
  • Run Window → Organizer → (select archive) → Validate App in Xcode — it should pass App Store submission checks.

And yes, that’s it. Quiet a process as promised, but the figuring it out part is what took a long time. But I hope, that this helps in preventing a severe headache for anyone else.

Hi there. I’m not sure if you got notified, but maybe my response from above helps you.

I just saw your message. Thank you for sharing your experience! I’ll follow what you wrote step by step and update you here with the result. Thanks again!

1 Like