The archive uploaded fine, and then the submission bounced before review even started. The email from App Store Connect read:
ITMS-91056: Invalid privacy manifest - The PrivacyInfo.xcprivacy file from the following path is invalid: "PrivacyInfo.xcprivacy". Keys and values in your app's privacy manifests must be valid.
No guideline number, no bug report, no reviewer. The file it names is probably not in your repo: it belongs to a third-party SDK inside your binary. This post covers what the file declares, which SDKs trigger the requirement, who owns the fix, and the audit worth running before your next upload.
What the file is
PrivacyInfo.xcprivacy is a property list that sits at the root of your app bundle (Contents/Resources/ on macOS). Apple's documentation describes it as recording "the types of data collected by your app or third-party SDK" and "the required reasons APIs your app or third-party SDK uses." Four top-level keys carry the declaration:
under app tracking transparency
att permission, requests to them fail
for tracking? purposes from a fixed list
approved reason codes you claim
The last key is the one that rejects uploads. Required reason APIs are a short list of ordinary calls (file timestamps, system boot time, disk space, active keyboards, user defaults) that Apple says "have the potential of being misused to access device signals to try to identify the device or user, also known as fingerprinting." The rule is blunt: "Regardless of whether a user gives your app permission to track, fingerprinting is not allowed." So if your code calls stat() or systemUptime or UserDefaults, the manifest must say which of the approved reasons covers it: E174.1 for checking disk space before writing files, CA92.1 for defaults only your app can access, 35F9.1 for measuring elapsed time. The declared reasons "must be consistent with your app's functionality as presented to users," and you "may not use the APIs or derived data for tracking."
Every binary files its own
A privacy manifest covers the code in its own bundle and nothing else. Apple's docs state it plainly: "Your third-party SDK can't rely on the privacy manifest files for apps that link the third-party SDK." For each executable or dynamic library that calls a required reason API, that library's bundle must contain its own manifest. A real iOS app is therefore a stack of declarations: one file for your code, plus one per SDK that needs it, each shipped by its vendor.
Which vendors must ship one is also spelled out. Apple maintains a list of "commonly used SDKs in apps on the App Store," 86 names covering the Firebase family, Flutter, Alamofire, RxSwift, RealmSwift, OneSignal, SnapKit, Lottie, SDWebImage, UnityFramework, and a run of Flutter plugins plus Cordova and Capacitor. The requirement per the page: "You must include the privacy manifest for any SDK listed below when you submit new apps in App Store Connect that include those SDKs, or when you submit an app update that adds one of the listed SDKs as part of the update. Signatures are also required in these cases where the listed SDKs are used as binary dependencies." And there is no version loophole: "Any version of a listed SDK, as well as any SDKs that repackage those on the list, are included in the requirement."
The dates that already passed
This is not an upcoming requirement; it is a settled one. The timeline:
- March 13, 2024. App Store Connect began emailing developers when an upload used required reason APIs without declaring reasons.
- May 1, 2024. Enforcement started: "apps that don't describe their use of required reason API in their privacy manifest file aren't accepted by App Store Connect," and listed SDKs added in a submission needed manifests and signatures. Apple's reminder put it as "Apps won't be accepted if they fail to meet the manifest and signature requirements."
- November 12, 2024. "Apps you submit for review in App Store Connect must contain a valid privacy manifest file." Every app, not just ones using the flagged APIs.
- February 12, 2025. The same validity requirement extended to the listed third-party SDKs: submissions "must contain a valid privacy manifest file for a certain number of commonly used third-party SDKs."
On failure, the email names the file and its path inside your bundle, which is how a bad manifest inside a dependency surfaces. Apple's own guidance for that case: "If an invalid file comes from a third-party SDK, contact its developer for an updated version of the SDK that includes a valid privacy manifest." In practice the culprit is an old pin: the SDK shipped a manifest two years ago and your lockfile predates it.
Where it meets the nutrition label
The manifest is the machine-checked half of a declaration you already make by hand. Xcode aggregates every manifest in the app into a privacy report (archive the build, then Generate Privacy Report from the organizer), and the report is "organized in a similar way to Privacy Nutrition Labels." Apple's instruction is to "refer to this report when you provide your app's privacy details in App Store Connect," the self-reported answers that render on your listing. The manifest tells the upload gate what your binary does; the report tells you what to answer; the listing is what users read. Google Play makes you file the equivalent by hand: the Data safety form covers every SDK in the binary on the same principle, and on both stores the sentence that matters is Apple's: "when you use a third-party SDK with your app, you are responsible for all the code the SDK includes in your app."
Our position
Treat the manifest as part of dependency vetting, not release paperwork. The audit we run before any App Store submission starts from the lockfile, not from memory: Package.resolved, Podfile.lock, or pubspec.lock is the dependency list that actually ships, cross-referenced against Apple's required SDK list with repackagers flagged. For every flag the question is the same one Apple asks: does the pinned version ship its own PrivacyInfo.xcprivacy? If it does not, the fix is an upgrade or a replacement, never a file we write on the vendor's behalf. Our own code gets the same check against the five categories, then the Xcode privacy report off the release archive gets reconciled against the App Store Connect answers so the label and the binary say the same thing.
The awkward case is an abandoned SDK on the list. If the vendor never shipped a manifest, there is no waiver and no way to declare on its behalf: your options are a fork that bundles a truthful manifest, a different SDK, or a feature cut. That is a dependency decision, and it is cheaper at selection time than at upload time.
The takeaway
Run this against your app before the next archive:
valid keys and values only, no extras
declared with a matching approved reason
list, repackagers included
manifest; binary deps carry a valid signature
archive before upload
the report, sdk collection included
manifest is a dependency decision, not a waiver
Dependency declarations like this are scope we price into custom software work, and the same audit we run on CashTaq before every submission. If your upload just bounced on a file you have never opened, send us the email.
// sources
// next step
We work this way on client projects too.
Tell us what you are making. We reply with a plan, a timeline, and a price.
