Your iOS build was rejected. Fix it and upload again without a Mac
Apple sent an email, or your upload failed, and you have no Mac. First check whether the fix needs a new build at all. Some do not. For the ones that do, this page gives the fix and the commands to archive, export and upload again in one day.
Does this need a new build?
Not every problem means a rebuild. These fixes happen in App Store Connect, from any browser:
- Screenshots, the description, and other product page text.
- Export compliance answers for a build marked Missing Compliance.
- Your App Privacy answers in App Store Connect.
Other fixes need a new build, so they need Xcode on a Mac. That covers an old Xcode or SDK, a privacy manifest, Info.plist strings, and code or SDK changes. Every new upload also needs a higher build number.
1. Built with an Xcode that is too old
Since April 28, 2026, Apple only accepts uploads built with Xcode 26 or later, using an iOS 26 SDK. A build from Xcode 16 fails this rule. To see what built an archive, read two keys from its app:
/usr/libexec/PlistBuddy -c 'Print :DTSDKName' -c 'Print :DTXcode' \ MyApp.xcarchive/Products/Applications/MyApp.app/Info.plist
On a GitHub macos-26 runner this printed iphoneos26.5 and 2660, which means Xcode 26.6. MacRun Macs have Xcode 27.1 as the default and Xcode 26.6 as well. Both pass the rule.
One catch: Apple says apps on the iOS 27.1 SDK will need iPhone Duo screenshots from April 2027. Our iPhone Duo guide shows how to take them.
2. Privacy manifest and required reason APIs
Some APIs need a stated reason, such as UserDefaults and file timestamps. The reasons go in a file named PrivacyInfo.xcprivacy. Since May 1, 2024, App Store Connect does not accept apps that skip this. Apple also rejects manifests with unexpected keys. Its email names the path of each bad file.
Here is a minimal manifest for an app that reads its own UserDefaults. CA92.1 is Apple's reason code for that use:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>Add it to your app target. Then check it is valid. We ran these on a good file and a broken one:
$ plutil -lint MyApp/PrivacyInfo.xcprivacy MyApp/PrivacyInfo.xcprivacy: OK $ plutil -lint bad.xcprivacy bad.xcprivacy: (Value missing for key inside <dict> at line 1)
After the archive, the file should sit at the root of the .app. Ours did. If the email names a third-party SDK, update that SDK. Its own manifest must cover its own API use.
3. Missing usage description strings
If your app uses the camera, photos or location, Info.plist needs a purpose string for it. Apple says access fails without one, and the app might crash. App Review guideline 5.1.1(ii) also asks that the string clearly describe your use of the data.
<key>NSCameraUsageDescription</key> <string>Scan receipts to add them to your expenses.</string>
Check the built app, not just the source file:
plutil -extract NSCameraUsageDescription raw \ MyApp.xcarchive/Products/Applications/MyApp.app/Info.plist
4. Export compliance
A build with no encryption answer shows Missing Compliance in TestFlight. You do not need a rebuild for this. Open the build in App Store Connect, click Manage, and answer the questions. To skip them next time, add this key to Info.plist. Use false only if your encryption is exempt, such as plain HTTPS:
<key>ITSAppUsesNonExemptEncryption</key> <false/>
5. Wrong or missing screenshots
Screenshots need no rebuild, but you need the right size. Apple requires at least one iPhone screenshot at the medium Dynamic Island size. That is 1179 x 2556 or 1206 x 2622 pixels in portrait. With no iPhone at hand, the Simulator makes them:
xcrun simctl boot "iPhone 17 Pro" xcrun simctl install "iPhone 17 Pro" MyApp.app xcrun simctl launch "iPhone 17 Pro" com.example.myapp xcrun simctl io "iPhone 17 Pro" screenshot shot.png sips -g pixelWidth -g pixelHeight shot.png
Our iPhone 17 Pro shot came out at 1206 x 2622, the required size. The iPhone 17 Pro Max gave 1320 x 2868, which fits the large set. Run xcrun simctl list devices available to see what is installed.
Rebuild and upload
Raise the build number, then archive. On our test runner this step took 12 seconds for a small SwiftUI app:
xcodebuild archive -project MyApp.xcodeproj -scheme MyApp \ -destination 'generic/platform=iOS' \ -archivePath build/MyApp.xcarchive \ MARKETING_VERSION=1.0.1 CURRENT_PROJECT_VERSION=3
Next, export a signed .ipa. Put this in ExportOptions.plist, with your own Team ID. The keys come from xcodebuild -help:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>method</key> <string>app-store-connect</string> <key>teamID</key> <string>ABCDE12345</string> <key>signingStyle</key> <string>automatic</string> </dict> </plist>
xcodebuild -exportArchive -archivePath build/MyApp.xcarchive \ -exportOptionsPlist ExportOptions.plist -exportPath build/export \ -allowProvisioningUpdates
Sign in to Xcode with your Apple Account first. Our unsigned test archive had no team, and the export stopped with "error: exportArchive No Team Found in Archive".
Apple's upload page lists Xcode, Transporter and altool. With altool, save an app-specific password in the keychain once. Then validate and upload:
xcrun altool --store-password-in-keychain-item altool -u you@example.com -p xxxx-xxxx-xxxx-xxxx xcrun altool --validate-app -f build/export/MyApp.ipa -t ios -u you@example.com -p @keychain:altool xcrun altool --upload-app -f build/export/MyApp.ipa -t ios -u you@example.com -p @keychain:altool
Or set destination to upload in ExportOptions.plist. Then -exportArchive sends the build to App Store Connect itself. Our publishing guide covers API keys and TestFlight.
Fix it in one day
A MacRun day pass costs $15, paid once with no renewal. It is a dedicated M6 Mac mini, ready in under 5 minutes. Xcode 27.1 and Xcode 26.6 are installed, with the iOS 27.1 simulator. You reach it over Tailscale with SSH or a VNC viewer. If review sends it back again, a week is $59. The Mac is wiped at the end, so push your code first.
Who should not rent a Mac for this
- If the fix is screenshots, text or export answers, use App Store Connect in a browser.
- Expo apps can rebuild with EAS Build on Expo's macOS machines. See building iOS apps on Windows.
- If you already build on Codemagic or GitHub Actions, push the fix and let CI rebuild.
Frequently asked questions
Can I fix an App Store rejection without a Mac?
+
Sometimes. Screenshots, text and export compliance answers are fixed in App Store Connect from any browser. A new Xcode, a privacy manifest or Info.plist change needs a new build, and that needs macOS.
Which Xcode version does App Store Connect require in 2026?
+
Since April 28, 2026, Apple requires uploads built with Xcode 26 or later, using an iOS 26 SDK. MacRun Macs have Xcode 27.1 as the default and Xcode 26.6 installed.
How do I add a privacy manifest to my iOS app?
+
Add a file named PrivacyInfo.xcprivacy to your app target. List each required reason API category with Apple's reason code, such as CA92.1 for an app's own UserDefaults. Check it with plutil -lint, then rebuild.
My TestFlight build says Missing Compliance. Do I need to rebuild?
+
No. Open the build in App Store Connect, click Manage, and answer the encryption questions. Add ITSAppUsesNonExemptEncryption to Info.plist in your next build to skip them.
What screenshot size does the App Store require for iPhone?
+
Apple requires at least one screenshot for iPhone with Dynamic Island, medium display: 1179 x 2556 or 1206 x 2622 pixels in portrait. Our iPhone 17 Pro simulator shot was 1206 x 2622.
How do I upload the new build without Xcode's window?
+
Export an .ipa with xcodebuild -exportArchive, then run xcrun altool --upload-app. Transporter also works. Apple lists both on its upload page.