Technical guide

How to prevent conflicts with iOS privacy manifests in iOS apps

Fix the Multiple commands produce PrivacyInfo.xcprivacy error, package SDK manifests in their own bundles and declare required-reason APIs before review.

  • One manifest per bundle

    The app and each framework or resource bundle carry their own PrivacyInfo.xcprivacy. Conflicts start when two land in the same place.

  • Check the archive

    Inspect what ships and generate Xcode's privacy report from the archive, not from the project view.

  • Declare real reasons

    Protection and diagnostics code often calls required-reason APIs. Each call needs an approved reason in the right manifest.

Most iOS privacy manifest conflicts come from packaging, not from the declarations themselves. The common one is the Xcode error “Multiple commands produce …/PrivacyInfo.xcprivacy”: a static library or CocoaPods dependency copies its manifest into the app bundle root, where it collides with yours. Fix it by shipping each dependency’s manifest inside its own resource bundle or framework, then check the archive and generate Xcode’s privacy report. Separately, make sure every required-reason API your code and SDKs call, including protection and diagnostics code, is declared with an approved reason.

For the product context, see data loss prevention and iOS app security.

Where manifests belong

A privacy manifest is a property list named PrivacyInfo.xcprivacy. On iOS, the app’s manifest sits at the root of the app bundle, and a framework’s manifest sits at the root of that framework bundle. Each bundle has its own file with the same name, which is legitimate. Xcode only fails when two build steps try to write a file to the same destination path.

SymptomLikely causeFix
“Multiple commands produce …/PrivacyInfo.xcprivacy”A dependency’s manifest is copied as a plain resource into the app bundle rootMove the dependency’s manifest into its own resource bundle or framework
ITMS-91053 “Missing API declaration” after uploadA required-reason API is called but not declared in the manifest of the code that calls itAdd the category and an approved reason to the right manifest
Invalid manifest reported for a bundleWrong keys or value types in that fileCorrect the file, or get a fixed release from the SDK vendor
Privacy report misses an SDKThe manifest is not in the archive, or is in the wrong placeCheck the bundle path in the archive

Fix “Multiple commands produce PrivacyInfo.xcprivacy”

This error appears most often with static libraries and with CocoaPods using static linkage. A static library (.a) cannot carry resources, so its files are copied into whatever target links it, which is your app. If both your app and the dependency provide PrivacyInfo.xcprivacy, two copy steps target the same path.

For CocoaPods dependencies

A pod that lists its manifest under resources copies it straight into the app bundle. The fix belongs in the podspec: ship the manifest under resource_bundles, so it lands in its own .bundle inside the app.

s.resource_bundles = {
  'ExampleSDK_Privacy' => ['Sources/PrivacyInfo.xcprivacy']
}

Most maintained pods have already made this change, so update the dependency first. If a vendor has not, raise it with them. As a stopgap, copy the dependency’s declarations into your app’s manifest and remove the duplicate from the copy step, and record that you now own those declarations.

For static libraries you build

Apple’s guidance is to create a static framework target containing the library’s sources and resources, and add the manifest to that target. A framework bundle has its own root, so its manifest no longer collides with the app’s.

For Swift packages and XCFrameworks

Declare the manifest as a resource in the package, because Xcode does not treat it as one by default. For XCFrameworks, check that each platform slice you ship contains its own manifest.

Generate and read the privacy report

After archiving, open Xcode’s Organizer, Control-click the archive and choose Generate Privacy Report. Xcode collects the manifests from the app and its bundles into one PDF. Use it to check three things:

  1. Every SDK you expect appears in the report. A missing SDK means its manifest is missing or misplaced.
  2. Data types and purposes match what the app and its SDKs really collect.
  3. Required-reason API categories are present for every SDK that calls them.

To inspect a specific file, use Show in Finder on the archive, then Show Package Contents, and follow the path to the bundle. Do not edit the manifest inside an archive: changing it breaks the signature. Fix the source and archive again.

Required-reason APIs in protection code

Some APIs can be misused for fingerprinting, so Apple requires a declared reason for each category used. App Store Connect has rejected uploads that call these APIs without a declaration since 1 May 2024. Security and diagnostics code often relies on them:

Category keyTypical use in protection or diagnostics code
NSPrivacyAccessedAPICategoryFileTimestampstat, getattrlist and file-date APIs used for integrity and environment checks
NSPrivacyAccessedAPICategorySystemBootTimesystemUptime and mach_absolute_time used for timing and anti-debugging checks
NSPrivacyAccessedAPICategoryDiskSpaceFree-space queries in diagnostics and crash reporting
NSPrivacyAccessedAPICategoryUserDefaultsStoring flags and configuration

Declare the reason that matches how the code uses the API, chosen from Apple’s list for that category, and put it in the manifest of the bundle that contains the code. An SDK declares its own use; your app’s manifest does not cover a framework’s calls. Ask every SDK and protection vendor which categories their code uses and which reasons they declare, and confirm their manifest appears in your privacy report.

Otukan Application Security fits your existing iOS build and release pipeline, and signing keys stay with you. Include the protected build in the same archive and privacy-report review as the rest of the release.

Release checklist

  • The app and every framework or resource bundle have exactly one manifest each.
  • The archive builds without “Multiple commands produce” errors.
  • The privacy report lists every SDK and matches real data collection.
  • Required-reason APIs in your code and protection code have approved reasons in the right manifest.
  • App extensions are checked as separate bundles.
  • Install, update, login and the sensitive journey pass on the signed build on a physical device.

Further reading

Common questions

  • What causes most iOS privacy manifest conflicts?

    Packaging, not the declarations themselves. The common case is a static library or CocoaPods dependency copying its PrivacyInfo.xcprivacy into the app bundle root, where it collides with the app's own manifest. Each bundle can legitimately carry a file with that name; Xcode fails only when two build steps write to the same destination path.

  • How should a CocoaPods dependency ship its privacy manifest?

    Under resource_bundles, not resources. A pod that lists its manifest under resources copies it straight into the app bundle, while resource_bundles places it in its own .bundle inside the app. Most maintained pods have already made this change, so update the dependency first and raise it with the vendor if not.

  • Does my app's manifest cover the required-reason APIs an SDK calls?

    No. An SDK declares its own use, and the reason belongs in the manifest of the bundle that contains the calling code. Ask every SDK and protection vendor which categories their code uses and which reasons they declare, then confirm their manifest appears in your Xcode privacy report.

  • Can I fix a privacy manifest by editing it inside the archive?

    No. Changing the manifest inside an archive breaks the signature, so fix the source file and archive again. To inspect a file, use Show in Finder on the archive, then Show Package Contents, and follow the path to the bundle that should contain it.

  • How does an Otukan-protected build fit the privacy manifest review?

    In the same way as the rest of the release. Otukan Application Security fits your existing iOS build and release pipeline, and signing keys stay with you. Include the protected build in the same archive and privacy-report review, and declare required-reason APIs used by protection code in the right manifest.

Keep privacy checks in your release process

Tell us your iOS distribution channel, framework, dependency manager and the build or review error you saw. We do not ask for binaries, signing keys, credentials or production data.

Or request a technical demo