Hive Hive
Sign in

ExtensionKit archive emits a wrong-directory warning with the standard copy destination

GitHub issue · Open

Metadata
Source
tuist/tuist #13461
Updated
Sep 22, 2026
Details

What happened?

An unsigned Release archive of an iOS app with an .extensionKitExtension target prints a warning that the extension is outside the app’s Extensions directory. The archive succeeds, and the extension is in the correct directory inside the .xcarchive.

I reproduced this with Tuist 4.158.2 and 4.209.0 on Xcode 27.1 beta, build 27A9269. The sample below has no dependencies, signing configuration or asset packs.

Tuist 4.209.0 generates the copy phase with:

dstPath = "$(EXTENSIONS_FOLDER_PATH)";
dstSubfolderSpec = 16;

During Archive, BuildProductsPath/Release-iphoneos/App.app is a symlink to InstallationBuildProductsLocation/Applications/App.app. The copy and validation tasks use the symlink path. Running the same embedded-binary validator against the extension’s actual path inside the completed archive produces no warning.

This may be an Xcode validation bug. Apple’s own ExtensionKit build specification uses exactly the same destination as Tuist. I am reporting the warning in generated archives, not claiming that Tuist puts the extension in the wrong directory.

For the iOS sample, changing only this phase to the app wrapper removes the warning:

dstPath = Extensions;
dstSubfolderSpec = 1;

Both archives contain Products/Applications/App.app/Extensions/Downloader.appex. Could Tuist avoid the warning during generation, or provide a supported way to override this destination without patching the generated project?

I have not tested signed export, TestFlight upload, macOS targets or a stable Xcode release. The observed problem is the archive warning.

How do we reproduce it?

Create an empty directory with the following files. An empty Tuist directory is also needed by Tuist 4.158.2 to locate the project root.

Project.swift:

import ProjectDescription
let project = Project(
name: "ExtensionArchive",
settings: .settings(base: ["LM_SKIP_METADATA_EXTRACTION": "YES"]),
targets: [
.target(
name: "App",
destinations: [.iPhone, .iPad],
product: .app,
bundleId: "com.example.ExtensionArchive",
deploymentTargets: .iOS("26.4"),
infoPlist: .extendingDefault(with: ["UILaunchScreen": [:]]),
sources: ["App/**"],
dependencies: [.target(name: "Downloader")]
),
.target(
name: "Downloader",
destinations: [.iPhone, .iPad],
product: .extensionKitExtension,
bundleId: "com.example.ExtensionArchive.Downloader",
deploymentTargets: .iOS("26.4"),
infoPlist: .extendingDefault(with: [
"EXAppExtensionAttributes": [
"EXExtensionPointIdentifier": "com.apple.background-asset-downloader-extension"
]
]),
sources: ["Downloader/**"],
settings: .settings(base: ["SKIP_INSTALL": "YES", "LM_SKIP_METADATA_EXTRACTION": "YES"])
)
],
schemes: [
.scheme(
name: "App",
shared: true,
buildAction: .buildAction(targets: [.target("App")]),
archiveAction: .archiveAction(configuration: .release)
)
]
)

App/App.swift:

import SwiftUI
@main
struct ExampleApp: App {
var body: some Scene {
WindowGroup { Text("Extension archive reproduction") }
}
}

Downloader/Downloader.swift:

import BackgroundAssets
import ExtensionFoundation
import StoreKit
@main
struct Downloader: StoreDownloaderExtension {}

Run from that directory:

mkdir -p Tuist
tuist generate --no-open
xcodebuild -workspace ExtensionArchive.xcworkspace -scheme App \
-configuration Release -destination 'generic/platform=iOS' \
-derivedDataPath build/DerivedData -archivePath build/App.xcarchive \
archive CODE_SIGNING_ALLOWED=NO

The archive succeeds but emits the warning below. The extension is present at:

build/App.xcarchive/Products/Applications/App.app/Extensions/Downloader.appex

For comparison, change only the Embed ExtensionKit Extensions copy phase to the wrapper destination shown above and run the same archive command again. The archive succeeds without warnings.

The older issue #4941 concerned an extension actually copied into PlugIns. This sample uses .extensionKitExtension and copies into Extensions.

Error log

warning: Downloader.appex is an ExtensionKit extension and must be embedded in the parent app bundle's Extensions directory, but is embedded in the parent app bundle's ../../../BuildProductsPath/Release-iphoneos/App.app/Extensions directory.
** ARCHIVE SUCCEEDED **

macOS version

27.0, build 26A428

Tuist version

4.209.0. Also reproduced with 4.158.2.

Xcode version

27.1 beta, build 27A9269

Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments

No GitHub comments yet.