Your archive validates locally, you hit Upload to App Store Connect, watch the progress bar finish, and minutes later an email lands: “ITMS-90426: Invalid Swift Support — The SwiftSupport folder is missing. Rebuild your app using the current public (GM) versions of Xcode and resubmit it.” Re-archiving and re-uploading produces the same error. The Frameworks folder looks fine, the project compiles cleanly, and Xcode says the archive is valid. The error is almost always about how a third-party framework was packaged or how your archive was assembled — the binary itself is correct; the layout is not.
Common causes
Ordered by likelihood.
1. Embedded framework was built with a different Swift version
You pulled in a vendored .xcframework or .framework (binary distribution) that was compiled with an older Swift toolchain. App Store Connect compares the framework’s SwiftSupport metadata to the public GM Xcode and rejects the mismatch.
How to spot it: otool -L YourApp.app/YourApp shows the binary’s Swift libs path; the framework’s Swift libs were compiled against libswiftCore.dylib from an older Xcode. Check Frameworks/<Framework>.framework/Info.plist for DTXcode version less than your current Xcode.
2. The framework was built without BUILD_LIBRARY_FOR_DISTRIBUTION
For a Swift framework to be safe to ship across Xcode versions, it must be built with BUILD_LIBRARY_FOR_DISTRIBUTION = YES. Without it, the framework’s ABI is non-stable and the archive’s SwiftSupport folder cannot be reconciled.
How to spot it: Inspect the vendored framework — if there is no .swiftinterface file alongside .swiftmodule, the framework was not built for distribution.
3. Pod / SPM pulled an x86_64 simulator slice into the device archive
When a .xcframework is missing or a .framework was built as a “fat” Mach-O including simulator slices, the App Store upload step rejects the SwiftSupport folder for the simulator architectures.
How to spot it: lipo -info YourApp.app/Frameworks/<Framework>.framework/<Framework> shows x86_64 or i386 slices alongside arm64. App Store binaries must contain device slices only.
4. Manually copied dynamic frameworks instead of using Embed Frameworks
If you drag-dropped a .framework into the project without checking Embed & Sign under Frameworks, Libraries, and Embedded Content, Xcode does not call the Run Script: Strip Invalid Architectures phase, and the SwiftSupport folder is not assembled correctly.
How to spot it: Open Build Phases → Embed Frameworks. If your framework is not listed there but appears in Link Binary With Libraries, that is the cause.
5. Uploaded with xcrun altool against an old Xcode
xcrun altool --upload-app uses the calling Xcode’s tools. If your CI machine has Xcode 15 active but your dev machine archived with Xcode 16, the upload step strips the wrong Swift support files.
How to spot it: xcode-select -p on the upload machine differs from the archive machine.
6. The framework ships an old swiftsupport payload that conflicts
Some old frameworks bundle their own SwiftSupport directory inside the framework. App Store Connect deduplication can pick the wrong copy.
How to spot it: find YourApp.app/Frameworks -name "SwiftSupport" -o -name "*.swiftmodule" lists multiple module locations across nested frameworks.
Before you start
- Save the exact ITMS-90xxx error number from the rejection email — different numbers mean different fixes.
- Make a copy of the failing
.xcarchiveto~/Desktop/ArchiveDebug.xcarchive— you will run a few inspections on it. - Identify which framework is the culprit; the rejection email sometimes names it, sometimes only says “SwiftSupport.”
Information to collect
- Output of
ls -la YourApp.xcarchive/Products/Applications/YourApp.app/Frameworks/. - Output of
lipo -info <each framework binary>. - Output of
otool -L <each framework binary> | grep -i swift. - Xcode version:
xcodebuild -versionon the archiving machine. - Each framework’s
Info.plistDTXcodeandDTSDKBuildvalues. - Pod / SPM declarations from
PodfileandPackage.resolved.
Step-by-step fix
Step 1: Identify the offending framework
Inspect every framework in the archive:
cd YourApp.xcarchive/Products/Applications/YourApp.app/Frameworks
for fw in *.framework; do
echo "=== $fw ==="
lipo -info "$fw/$(basename $fw .framework)"
/usr/libexec/PlistBuddy -c "Print :DTXcode" "$fw/Info.plist" 2>/dev/null
ls "$fw/Modules/$(basename $fw .framework).swiftmodule/" 2>/dev/null
done
Look for: simulator architectures, missing .swiftinterface files, or DTXcode significantly older than your archive Xcode.
Step 2: Replace fat frameworks with XCFrameworks
If a vendored framework includes simulator slices, ask the vendor for an .xcframework, or convert yourself:
# Extract device-only slice
lipo -extract arm64 \
Path/To/Old.framework/Old \
-o Path/To/Old.framework/Old-device
mv Path/To/Old.framework/Old-device Path/To/Old.framework/Old
# Or build an XCFramework from device + sim archives
xcodebuild -create-xcframework \
-framework Path/To/Device.framework \
-framework Path/To/Simulator.framework \
-output Path/To/Combined.xcframework
Replace the project reference with the .xcframework — Xcode auto-selects the right slice per build.
Step 3: Rebuild any in-house Swift framework with library evolution
In the framework target’s Build Settings:
BUILD_LIBRARY_FOR_DISTRIBUTION = YES
SWIFT_INSTALL_OBJC_HEADER = YES
SKIP_INSTALL = NO
Then archive the framework target:
xcodebuild archive \
-scheme MyFramework \
-destination "generic/platform=iOS" \
-archivePath ./build/iOS.xcarchive \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
Repeat for simulator with -destination "generic/platform=iOS Simulator", then xcodebuild -create-xcframework.
Step 4: Ensure every framework is Embed and Sign in the app target
App target → General → Frameworks, Libraries, and Embedded Content. Every dynamic framework should show Embed & Sign. Static libraries are Do Not Embed. If a framework shows Do Not Embed but should be dynamic, switch it.
Step 5: Match Xcode versions across machines and CI
Pin Xcode in your CI config:
xcode_version: "16.0"
On dev: sudo xcode-select -s /Applications/Xcode_16.0.app/Contents/Developer. Mismatched Xcode between the archive step and the upload step causes the SwiftSupport stripper to use the wrong source.
Step 6: Clear DerivedData and rebuild cleanly
Cached Swift modules cause stale SwiftSupport payloads:
rm -rf ~/Library/Developer/Xcode/DerivedData/*
rm -rf ~/Library/Caches/org.swift.swiftpm
xcodebuild clean -workspace YourApp.xcworkspace -scheme YourApp
Then re-archive from clean state. Skipping this step is the single most common reason a “fixed” project still uploads the old broken framework.
Step 7: Upload via the right tool
Use Xcode’s Organizer (Window → Organizer → Archives → Distribute App) or xcrun altool from the same Xcode you archived with:
xcrun altool --upload-app -f YourApp.ipa -t ios \
-u "you@example.com" -p "@keychain:AC_PASSWORD"
Or the newer notarytool / Transporter route:
xcrun notarytool submit YourApp.ipa --keychain-profile "AC_PROFILE"
Watch the upload log; the SwiftSupport processing step prints which frameworks it processed.
Verify
- New archive’s
Frameworks/contains onlyarm64binaries. - Each Swift framework’s module folder contains
.swiftinterfacefiles alongside.swiftmodule. - App Store Connect upload completes without ITMS-90426 / 90427.
- The processed build appears in TestFlight within 5-30 minutes.
- Validate Xcode → Window → Organizer → Validate App → no warnings about Swift support.
Long-term prevention
- Prefer
.xcframeworkfor every binary dependency; fat frameworks are deprecated and will keep biting you. - Ask vendors for distribution-built frameworks; if they refuse, build from source where possible.
- Lock Xcode version in CI and on every dev machine via
.xcode-versionfile ornvm-style switcher. - Add a pre-upload script that runs
lipo -infoon every framework in the archive and fails the build if simulator slices appear. - Track which Swift / Xcode version each vendored framework was built against; recompile on Xcode major upgrades. See TestFlight Build Stuck Processing for the downstream symptom.
- Avoid drag-dropping
.frameworkfiles into the project; use Swift Package Manager or Pods which handle the embed step correctly.
Common pitfalls
- Re-uploading the same
.ipaafter “fixing” Xcode settings — without re-archiving, your IPA is unchanged. - Mixing static and dynamic versions of the same framework; the App Store sees duplicate symbols and rejects.
- Setting
BUILD_LIBRARY_FOR_DISTRIBUTION = YESon the App target instead of the Framework target. - Forgetting that CocoaPods uses
use_frameworks!to decide static vs dynamic; switching this requires deintegrate + reinstall. - Submitting from a Mac with a beta Xcode while the archive was built with GM Xcode — Apple Beta Xcode archives are not accepted for production submission.
- Assuming
xcrun altoolalways matches the active Xcode —xcode-selectsetting is what determines it.
FAQ
Q: The vendor says their framework supports App Store. Why does Apple reject it?
Most likely the framework was built with BUILD_LIBRARY_FOR_DISTRIBUTION = NO or shipped as a fat framework including simulator slices. Ask for an .xcframework built with the latest Xcode GM. If they refuse, your only remedies are to build from source or drop the dependency.
Q: Will Bitcode help here?
Bitcode is deprecated since Xcode 14 — disable it in Build Settings (ENABLE_BITCODE = NO). Keeping it on with modern Xcode adds risk without benefit and can intersect with Swift support errors in obscure ways.
Q: I am using Swift Package Manager. Can this still happen?
Yes, if the SPM package vends a binary target (.binaryTarget(name:url:)) pointing to a problematic XCFramework. Inspect the binary in ~/Library/Developer/Xcode/DerivedData/<proj>/SourcePackages/artifacts/.
Q: Apple says rebuild with GM Xcode but I used GM Xcode. What now?
Check the DTXcode and DTSDKBuild keys in each vendored framework’s Info.plist. If any one of them was built with an older Xcode, that is the framework Apple is rejecting; you need a new build of that framework, not of your app.
Q: Can I just delete the framework’s SwiftSupport folder manually?
No. Xcode regenerates the archive’s SwiftSupport during export; manual edits get overwritten. Fix the framework’s build settings instead.
Related
- TestFlight Build Stuck Processing
- Expired Provisioning Profile Build
- New Build Not Appearing
- TestFlight Build Expired
Tags: #Troubleshooting #ios #xcode #swift #archive