You uploaded a build to App Store Connect, watched the processing spinner, and an hour later an email landed with the subject 'ITMS-91053: Missing API declaration'. The body lists NSPrivacyAccessedAPICategoryDiskSpace and says your app references an API that requires a reason in the privacy manifest. The first question most developers ask is not how to add the entry, it is which SDK called the API in the first place.
Short answer
Apple's static scanner found a call to a disk-space API (typically volumeAvailableCapacity, volumeAvailableCapacityForImportantUsage, or systemFreeSize) somewhere in your compiled binary and no PrivacyInfo.xcprivacy file declares the use. The fix is two steps: add an NSPrivacyAccessedAPITypes entry with the category NSPrivacyAccessedAPICategoryDiskSpace and one of four approved reasons (E174.1, 85F4.1, B728.1, 7D9E.1), then identify which dependency made the call so the declaration is honest. Per Apple's documentation on describing use of required reason API, the requirement has been enforced at upload since May 1, 2024.
What you should know
- The warning is now an upload block. Since May 1, 2024, ITMS-91053 stops the build at App Store Connect processing, before TestFlight or App Review see it.
- Four approved reasons exist for disk space, and only those four. Inventing a custom string causes the same upload failure.
- The reason must match the actual API behavior, not the most generic choice. Apple expects E174.1 for write-time checks, not for display.
- The SDK is usually the source, not your own code. Crash reporters, ad networks, and device-info libraries are the common offenders.
- Bundled SDK manifests count toward the combined report, but only if Xcode picks them up. SPM has had recognition bugs that forced app-side declarations.
What does the ITMS-91053 warning actually say?
The email arrives from [email protected] and lists every required-reason API category Apple flagged on the upload. A disk-space entry reads roughly: 'ITMS-91053: Missing API declaration. Your app's code in the executable references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryDiskSpace.' The same email may list other categories (UserDefaults, FileTimestamp, SystemBootTime, ActiveKeyboards) in separate lines.
The critical detail is what the email does not say. It does not name the file, the function, the symbol, or the SDK that made the call. Apple's static scan operates on the linked binary, so the report is bound to the final executable rather than to source. For an Xcode project that imports half a dozen frameworks, the path from warning to root cause is yours to trace.
Per Apple's NSPrivacyAccessedAPIType reference, the disk-space category covers any API that returns information about device storage capacity or availability. The list includes volumeAvailableCapacityKey, volumeAvailableCapacityForImportantUsageKey, volumeAvailableCapacityForOpportunisticUsageKey, volumeTotalCapacityKey, systemFreeSize, and systemSize. A single use of any of these triggers the warning.
Which reason code should you declare?
Apple publishes exactly four approved reasons for the disk-space category. Each one corresponds to a different real use of the data, and the choice matters because Apple expects the declaration to match the call.
| Reason code | Approved use | Off-device transfer allowed? |
|---|---|---|
| E174.1 | Check free space before writing a file, or free space by deleting files when storage is low. The app must visibly react to the value. | No, except to skip a download when space is low. |
| 85F4.1 | Display the disk-space value to the user, in bytes or as minutes of media. | No, the value cannot leave the device. |
| B728.1 | A health research app detecting low disk space that would affect study data collection. | No. |
| 7D9E.1 | Include the value in an optional bug report the user chose to submit. | Yes, if the user consents, and only to investigate the report. |
For most apps, E174.1 is the right answer. A media app that checks whether a download fits, a journaling app that warns when the database file is approaching the volume limit, a build that asks 'do I have room to cache this asset' all fall under E174.1. Pick 85F4.1 only if you actually render the number on a screen.
7D9E.1 is the trap. Some teams pick it because 'bug report' sounds harmless, but the reason restricts the use to a report the user opted into and explicitly submitted. A crash reporter that collects disk space silently in the background does not qualify, and declaring 7D9E.1 for that case creates a mismatch between the declaration and the binary behavior.
How do you find which SDK triggered the warning?
The scan runs on the linked Mach-O binary, so the trace runs there too. The shortest path is to inspect the binary symbols after the build that produced the warning.
From a Terminal at the IPA path:
unzip MyApp.ipa -d ipa/
nm -u ipa/Payload/MyApp.app/MyApp | grep -i -E 'volumeAvailableCapacity|systemFreeSize|systemSize'
The nm output lists undefined external symbols. A line containing _OBJC_CLASS_$_NSURL near a volumeAvailableCapacity reference points to Foundation's URL resource value API, which is the most common entry point. A line referencing NSFileManager and systemFreeSize points to the older file-manager path.
That tells you the API was called. The harder question is which library called it. Two follow-ups narrow it down:
strings ipa/Payload/MyApp.app/MyApp | grep -i 'volumeAvailableCapacity'
otool -L ipa/Payload/MyApp.app/MyApp
The strings output sometimes embeds the calling framework's class name near the symbol literal. The otool -L output lists every linked dynamic library, which is your candidate list. Cross-reference each candidate against its vendor's privacy manifest documentation. Known repeat offenders include Sentry's iOS SDK (which historically called disk-space APIs from its crash context collector, tracked in getsentry/sentry-cocoa issue #3789), Firebase Crashlytics, Bugsnag, Google Mobile Ads, and DeviceKit.
For a no-code or vibe-coded build where you do not have the IPA on disk, the same audit runs on the archived .xcarchive under Products/Applications/. The compiled binary is the only honest record because the SDK that made the call may have been added by a project rule the planner ran without surfacing in chat.
How do you write the PrivacyInfo.xcprivacy entry?
The file is a property list. If your project does not already have one, create PrivacyInfo.xcprivacy at the project root and add it to the app target under Build Phases, Copy Bundle Resources. The minimal disk-space declaration looks like:
<?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>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
</array>
</dict>
</plist>
Xcode treats the file as a structured property list, so the easier edit path is File, New, File, App Privacy, then pick the category from the dropdown and the reason from the inner dropdown. The XML behind the dropdown is the same.
Per Apple's NSPrivacyAccessedAPITypeReasons documentation, the reasons array can contain more than one entry if your app uses the API for more than one approved purpose. A media app that both checks free space before downloads (E174.1) and displays remaining capacity on a settings screen (85F4.1) declares both.
Rebuild, re-archive, and re-upload. A successful processing pass without a new ITMS-91053 email confirms the declaration was accepted.
What if an SDK already ships a privacy manifest?
Xcode bundles every linked SDK's PrivacyInfo.xcprivacy and merges them into one report Apple's scanner reads at upload time. In principle, an SDK that already declares its disk-space use covers itself, and you do not need a duplicate entry. In practice, two failure modes recur.
The first is Swift Package Manager packaging. A known case, tracked in the DeviceKit SPM issue #408, is a library whose privacy manifest sits inside a resource bundle that Xcode includes at build time but Apple's scanner does not pick up reliably. The maintainer reported that removing the library let the app pass, then adding a manual disk-space declaration to the app target let the library stay. The pattern was fixed upstream in a later version, but older pinned versions still need the workaround.
The second is CocoaPods integration of a framework whose privacy manifest is in the wrong path. Apple's scanner looks for PrivacyInfo.xcprivacy at the framework root or inside the resource bundle that the framework target ships. A pod that places the file at the project root rather than inside the framework gets it copied into the wrong target, and Apple's report misses it.
The practical move when an SDK 'should' cover the declaration but the warning keeps coming back is to add the declaration to your app's PrivacyInfo.xcprivacy as a defensive measure, file an issue with the SDK maintainer, and remove the redundant entry once the upstream fix ships. PTKD.com (https://ptkd.com) automates this audit on uploaded IPAs by extracting every linked binary's privacy manifest and listing which required-reason APIs the binary calls without a matching declaration, so the trace from warning to source takes minutes instead of hours.
What to watch out for
Four patterns trip up developers fixing ITMS-91053 for disk space.
First, picking the broadest-sounding reason. 7D9E.1 reads like a catch-all because 'bug report' covers many cases, but the approved use is narrow: the user must opt into the report. A silent crash reporter does not qualify, and declaring 7D9E.1 anyway puts your binary behavior at odds with your manifest declaration.
Second, copying a manifest from a tutorial without checking which reasons match. A tutorial written for a media player that displays storage capacity uses 85F4.1, which does not apply to a fintech app that only checks free space before writing a local cache. Use the table above to confirm the match.
Third, fixing the manifest and forgetting to rebuild and re-archive. Xcode caches the archive output, and an upload from a pre-edit archive sends the old binary with the old (missing) manifest. The fix is to delete the old archive in Window, Organizer, then archive fresh.
Fourth, treating the bundled SDK manifest as automatic coverage. The merge step usually works, but the SPM and CocoaPods edge cases above mean an app can ship a 'correct' SDK manifest and still get the warning. The honest test is the upload itself.
Key takeaways
- ITMS-91053 for disk space is a binary-level finding. The reason your code does not show the call is usually that an SDK made it. Inspect the linked binary, not the source tree.
- Only four approved reason codes exist: E174.1, 85F4.1, B728.1, 7D9E.1. Match the reason to the actual use, not to the most generic option.
- A bundled SDK privacy manifest covers the SDK in principle, but SPM and CocoaPods packaging quirks have been observed to break the merge. When the warning persists, add the declaration to your app manifest defensively.
- Some teams hand the pre-submission scan of required-reason API declarations to platforms like PTKD.com (https://ptkd.com) to skip the manual
nmandotooltrace on every release. - Rebuild and re-archive after the manifest edit. Xcode caches happily, and the upload pipeline does not know the difference between a stale archive and a fresh one.




