Privacy

    How do I fix 'Missing API declaration' for disk_space?

    Apple ITMS-91053 missing API declaration warning for NSPrivacyAccessedAPICategoryDiskSpace in App Store Connect

    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 codeApproved useOff-device transfer allowed?
    E174.1Check 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.1Display the disk-space value to the user, in bytes or as minutes of media.No, the value cannot leave the device.
    B728.1A health research app detecting low disk space that would affect study data collection.No.
    7D9E.1Include 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 nm and otool trace 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.
    • #privacy-manifest
    • #itms-91053
    • #disk-space
    • #ios
    • #required-reason-api
    • #app-store-connect

    Frequently asked questions

    Which reason code should I pick for NSPrivacyAccessedAPICategoryDiskSpace?
    Most apps need E174.1, which covers checking free space before writing a file or freeing space when storage runs low. Pick 85F4.1 only if you display the disk number to the user. Pick 7D9E.1 if the value goes into an opt-in bug report. B728.1 is reserved for health research apps. The reason must match what the API call actually does, not the most generic one available.
    Why did Apple flag disk_space when my code never calls it?
    A third-party SDK called it. Common offenders are crash reporters (Sentry, Firebase Crashlytics, Bugsnag), analytics frameworks, ad SDKs (Google Mobile Ads), and device-info libraries like DeviceKit. The compiled binary contains the symbol, so Apple's static scan sees it regardless of which package introduced it. Find the SDK by greping the binary or by checking each vendor's privacy manifest documentation.
    Is ITMS-91053 a rejection or just a warning?
    Since May 1, 2024, ITMS-91053 blocks the build at upload to App Store Connect. Before that date it was an email warning that did not stop submission. In 2026 the warning email and the upload block are the same event, so a build that triggers ITMS-91053 cannot reach TestFlight or App Review until you ship a PrivacyInfo.xcprivacy that declares the API.
    Does the SDK's bundled PrivacyInfo.xcprivacy count, or do I need my own?
    Both. Apple combines every PrivacyInfo.xcprivacy from your app and from each linked SDK into one report. An SDK that ships its own manifest covers itself. The known exception was DeviceKit 5.2.3 distributed via Swift Package Manager, where the bundle was not recognized at review time and the app maintainer had to declare the API in their own manifest until the SDK shipped a fix.
    Can I just delete the SDK that triggers the warning?
    Sometimes. If the disk-space call comes from a feature you never use (a crash reporter that profiles device storage at startup), removing the SDK or upgrading to a version that ships a privacy manifest is cleaner than declaring an API you do not actually need. If the SDK is core (an ad network you depend on for revenue), add the declaration and accept the disclosure.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free