How do I fix ITMS-91053 for the file timestamp API?

You uploaded a build to App Store Connect, the processing email arrived a few minutes later, and the body referenced ITMS-91053 with NSPrivacyAccessedAPICategoryFileTimestamp flagged. The app runs in the simulator, the previous TestFlight build cleared, but today the upload is held with the status Invalid Binary. The question is what that one line in the email actually means, which call inside the binary is responsible, and the smallest change that lets the next upload process cleanly.
Short answer
App Store Connect rejects builds that read file creation, modification, or access timestamps without declaring those calls in a PrivacyInfo.xcprivacy file. The fix is a privacy manifest containing NSPrivacyAccessedAPICategoryFileTimestamp paired with an approved reason code: C617.1 for files in the app container, 3B52.1 for user-granted paths, DDA9.1 for timestamps shown to the user, or 0A2A.1 for third-party SDK wrappers. Apple has enforced the rule for new submissions since 1 May 2024, per the Apple Developer privacy manifest documentation.
What you should know
- ITMS-91053 is a privacy manifest error, not a code-signing or entitlement error. App Store Connect scans the binary for symbols associated with required reason APIs and refuses to process the build when no matching manifest entry is present.
- NSPrivacyAccessedAPICategoryFileTimestamp is one of four required reason API categories. The others are disk space, system boot time, and user defaults. File timestamp is the category most often raised on apps that read file attributes for cache management or upload logic.
- There are four approved reason codes for the file timestamp category. Apple's Describing use of required reason API page lists C617.1, 3B52.1, DDA9.1, and 0A2A.1. Picking the wrong one is rare; picking none is the usual error.
- The manifest belongs to whichever target calls the API. If your code reads modificationDate on a URL, the app target carries the entry. If a vendor framework calls stat or getattrlist, that framework needs its own manifest, not yours.
- The rule started as a warning in March 2024 and became a hard block on 1 May 2024. Before the cutover, builds without manifests still uploaded and the email was informational. Today the binary is held in App Store Connect and a new build is required.
- A correct manifest is roughly fifteen lines of plist and adds no runtime behaviour. It is metadata read during ingestion and surfaced in the Privacy Nutrition Label on the App Store listing.
Why does App Store Connect return ITMS-91053 for file timestamp APIs?
The short answer is that Apple now scans every uploaded binary for symbols associated with a defined set of required reason APIs, and it refuses to process a build that references one of those symbols without a matching declaration in a privacy manifest. The file timestamp group covers NSURL resource keys like NSURLCreationDateKey, NSURLContentModificationDateKey, and NSURLContentAccessDateKey, plus NSFileManager methods like attributesOfItemAtPath, plus the BSD calls stat, fstat, lstat, fstatat, and the getattrlist family.
The scan does not read your Swift or Objective-C source. It reads the compiled Mach-O. A project that builds and runs without complaint can still fail on upload because a linked framework calls one of those symbols and the symbol survived stripping. Apple's TN3183 technote describes the rule as an audit of API usage, not a behavioural check, which is why the diagnostic appears during processing rather than at runtime.
Which reason code should I pick for the file timestamp category?
Apple publishes four approved reasons under NSPrivacyAccessedAPICategoryFileTimestamp. Each one matches a different real-world purpose, and a single manifest entry can list more than one when the app legitimately spans cases.
The most common reason is C617.1. It covers reading timestamps, size, or other metadata for files inside the app container, the app group container, or the app's CloudKit container. Cache eviction logic, "files older than seven days" cleanup, and resumable downloads usually sit here.
3B52.1 covers files or directories that the user explicitly granted access to, typically through UIDocumentPickerViewController or a security-scoped bookmark. Editor apps, file viewers, and any tool that takes a user-selected path use this code.
DDA9.1 is for cases where the timestamp is displayed in the interface to the person using the device, for example a "last modified" label in a file list. If the read exists only to render UI, this is the right code.
0A2A.1 is restricted to third-party SDKs that wrap a file timestamp API behind a function the host app calls. The SDK ships this declaration in its own manifest; an app developer does not use 0A2A.1 for first-party code.
Cases reported on the Apple Developer forum thread on stat() show that submitting C617.1 when 3B52.1 would have been more accurate does not block the upload. Apple does not police the alignment between the description and the call at ingestion. The audit only checks that one approved reason is present for the category. Picking the reason that genuinely matches the call is still the safer practice, because a later human review pass can ask about it.
How do I add the entry to PrivacyInfo.xcprivacy?
The file goes into the bundle of the target that calls the API. For a plain iOS app with no embedded frameworks, that is the app target, and PrivacyInfo.xcprivacy sits at the root of the .app folder. Add it via File, New, File from Template, App Privacy under the Resource section. Xcode generates an empty plist and registers it with the current target.
The one step developers miss is target membership. Open the File Inspector on the new manifest, scroll to Target Membership, and confirm the app target box is ticked. A manifest in the project navigator but outside target membership never reaches the .app bundle, and ITMS-91053 returns on the next upload.
The smallest valid entry for a file-timestamp-only fix is one dictionary inside the NSPrivacyAccessedAPITypes array, with NSPrivacyAccessedAPIType set to NSPrivacyAccessedAPICategoryFileTimestamp and NSPrivacyAccessedAPITypeReasons set to an array containing one or more reason strings.
<?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>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
</dict>
</plist>
If the same target also reads disk space, user defaults, or system boot time, those go in as sibling dictionaries inside the same NSPrivacyAccessedAPITypes array. After editing the plist, archive the project, right-click the .ipa in Finder and Show Package Contents, and confirm PrivacyInfo.xcprivacy sits at the top level of the .app folder before the next upload.
How do I find which framework calls a file timestamp API?
A build that compiles fine but fails on upload usually carries the call inside a CocoaPods, Swift Package Manager, or vendored .xcframework dependency. There are three reliable paths to identify the responsible SDK.
The first is symbol grep. After archiving, open the .ipa, navigate to Payload/.app/Frameworks, and run nm -u on each binary to list referenced symbols. A match on stat, fstat, getattrlist, attributesOfItemAtPath, or any NSURL resource key with Date in the name narrows the candidate list quickly. TN3183 recommends this approach for finding the responsible SDK.The second is the SDK's own changelog. Most major vendors began shipping privacy manifests in spring 2024. Firebase, Google Mobile Ads, AppsFlyer, Adjust, Sentry, Branch, and Lottie all published manifest-bearing releases by mid-2024. If the Podfile or Package.resolved is pinned to a pre-April 2024 version, bumping to a current release usually clears the rejection without manual plist work.
The third is process of elimination. Comment out a suspect SDK initialization, archive, and upload to a separate test app record. If the rejection disappears, that SDK is the source. The approach is slow but useful for closed-source dependencies without a public changelog.
Which file timestamp APIs trigger the scan?
The table below collects the most common entry points that App Store Connect's scanner flags under NSPrivacyAccessedAPICategoryFileTimestamp, based on Apple's published list.
| API or symbol | Framework | Typical caller |
|---|---|---|
| NSURLContentModificationDateKey | Foundation (URLResourceKey) | Cache freshness, sync logic |
| NSURLCreationDateKey | Foundation | Sort by date in a file list |
| NSURLContentAccessDateKey | Foundation | LRU eviction policies |
| attributesOfItemAtPath, attributesOfFileSystemForPath | NSFileManager | Older Objective-C code paths |
| stat, fstat, lstat, fstatat | BSD libc | C and C++ libraries, analytics SDKs |
| getattrlist, getattrlistat, fgetattrlist | BSD libc | Lower-level performance code |
Apple groups every entry above under a single category, so one reason code on a single dictionary entry covers any combination of these calls. There is no separate code per symbol.
What to watch out for
- A manifest in the wrong target. Adding PrivacyInfo.xcprivacy to the project but leaving the app target unchecked produces a build with no manifest in the .app bundle. App Store Connect sees nothing and continues to reject. Verify by unzipping the .ipa.
- A vendor SDK that ships its own manifest, but a stale version. Vendors sometimes correct an incomplete reason list in a later release. A locked Podfile may still ship the older, incomplete manifest from the framework, and ITMS-91053 returns.
- Reusing the same build number. App Store Connect deduplicates by version plus build number. After fixing the manifest, increment CFBundleVersion before uploading. Otherwise Transporter may succeed at the network layer while the binary is silently ignored.
- Confusing this rule with App Tracking Transparency. ATT and the privacy manifest are separate systems. An app can have a clean ATT setup and still fail ITMS-91053. They share the word privacy and nothing else.
- Treating the privacy manifest as a substitute for a security review. The manifest is a disclosure of API usage. It does not check whether secrets are hardcoded in the binary, whether SDK initializers leak API keys at first launch, or whether storage paths sit unencrypted on disk. Those checks live in a separate pass against OWASP MASVS. For builders who want an external read of the compiled IPA before submission, PTKD.com (https://ptkd.com) is one platform focused specifically on pre-submission scanning of iOS and Android binaries for OWASP MASVS controls.
Key takeaways
- ITMS-91053 with NSPrivacyAccessedAPICategoryFileTimestamp is a missing privacy manifest entry, not a code defect. Add the PrivacyInfo.xcprivacy file with the right reason code and the upload will process.
- Pick the reason code that matches the real call: C617.1 for app-container files, 3B52.1 for user-granted paths, DDA9.1 for timestamps shown in the UI, 0A2A.1 only for third-party SDK wrappers.
- Confirm the file is in the right target and actually shipped inside the .app bundle. The most common repeat-rejection cause is a manifest outside target membership.
- If first-party code does not call file timestamp APIs, look at third-party SDKs. Bump them to a release dated after April 2024, when most major vendors began shipping their own manifests, before writing manual plist entries.
- Increment the build number after every fix. App Store Connect deduplicates by version plus build, and reusing the same value can hide a corrected build behind the previous rejected one.
- The privacy manifest is a disclosure, not an audit. For developers who want an independent read of the compiled binary against OWASP MASVS before submission, platforms like PTKD.com (https://ptkd.com) run that check on the IPA itself and flag manifest gaps along with secret storage and network issues.
- #itms-91053
- #privacy manifest
- #ios
- #app store connect
- #file timestamp
- #required reason api
Frequently asked questions
- Is ITMS-91053 a hard rejection or just a warning?
- Since 1 May 2024 it is a hard rejection for new App Store submissions and TestFlight builds, per Apple's published enforcement timeline. Before that date the same message arrived as informational email and the build still processed. Today the build is held in App Store Connect with the status Invalid Binary, and the developer cannot ship until the manifest is corrected and a new build is uploaded with a higher build number.
- Which reason code do I pick for file timestamps?
- Pick the reason that matches the actual call. C617.1 covers files in the app container, app group, or CloudKit container. 3B52.1 covers files the user picked through a document picker or security-scoped bookmark. DDA9.1 is for timestamps displayed in the user interface. 0A2A.1 is reserved for third-party SDKs that wrap file timestamp APIs. App Store Connect accepts any of the four at ingestion.
- Why does ITMS-91053 still appear after I added the manifest?
- Three common reasons. First, the PrivacyInfo.xcprivacy file is not part of the target that ships; check Target Membership in the File Inspector. Second, the manifest is in your app but the file timestamp call lives inside a third-party framework that needs its own manifest. Third, the build number was not incremented, so App Store Connect kept the old binary in processing instead of ingesting the new one.
- Do I need a manifest if I only use Apple frameworks?
- Yes if your app or any first-party code calls one of the file timestamp APIs listed in Apple's Required Reason API table, such as NSURLContentModificationDateKey, attributesOfItemAtPath, or stat. The required reason rule applies to your own code, not only to vendor SDKs. The manifest can sit at the root of the app target with a single NSPrivacyAccessedAPICategoryFileTimestamp entry and one reason code such as C617.1.
- Will adding a privacy manifest change anything users see?
- No. The privacy manifest is metadata read by App Store Connect during ingestion and surfaced in the Privacy Nutrition Label that Apple shows on the App Store listing. Runtime behaviour of the app does not change, no new permission prompt appears, and existing users see no difference. The manifest only affects what Apple's automated review pipeline accepts and what the public listing displays for privacy disclosures.
Keep reading
Journal · PrivacyHow do I fix ITMS-91053 for the disk space API?ITMS-91053 lands when your iOS binary calls a disk space API without naming a reason. Here is how to spot the call, write the manifest entry, and resubmit.8 min read
Journal · PrivacyHow do I fix the 'Missing API declaration' for disk_space?App Store Connect rejects builds that call disk-space APIs without an approved reason in PrivacyInfo.xcprivacy. The fix takes five minutes.8 min read
Journal · PrivacyHow do I fix the ITMS-91053 missing file_timestamp declaration?App Store Connect rejected your upload because the binary calls a file_timestamp API and PrivacyInfo.xcprivacy is missing an approved reason.8 min read
Journal · PrivacyHow do I use the Required Reason API for UserDefaults in Expo?Apple flags NSUserDefaults under the Required Reason API. In Expo, the fix is one block in app.json with the right code: CA92.1, 1C8F.1, or C56D.1.9 min read
Scan your app in minutes
Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.
Try PTKD free