Unable to write to file system when building for My Mac (Designed for iPad)

Our app is unable to write to its own sandbox container on macOS when run via “My Mac (Designed for iPad)”. This is not an issue when the app runs on iPhone or on iPad. This seems to affect all attempts to write to the file system including: UserDefaults Core Data (SQLite) Firebase (Analytics, Crashlytics, Sessions) File creation (PDFs, temp files, etc.)

We're seeing the following errors in the console:

Operation not permitted / NSCocoaErrorDomain Code=513: Permissions error when writing to disk. CFPrefsPlistSource: Path not accessible: Failure to write to UserDefaults. Cannot synchronize user defaults to disk: UserDefaults write blocked. CoreData: No permissions to create file: Core Data SQLite store can't be created. Firebase: Failed to open database: Firebase can't initialize local storage. CGDataConsumerCreateWithFilename: failed to open ... for writing: PDF generation fails due to temp directory access issues.

Created a test project to try and reproduce the issue but unable to do so in the test project, even when setting all the build settings the same as the project having issues.

Answered by DTS Engineer in 863610022

Our app is unable to write to its own sandbox container on macOS when run via “My Mac (Designed for iPad)”. This is not an issue when the app runs on iPhone or on iPad.

So, the one thing to understand here is that the sandbox enforcement system operates at a low enough level of the system that I can't really "fail"*, at least not in a broad, systemic way. That's particularly true of apps running compatibility mode, which are designed to operate with very limited access.

*Putting that in more concrete terms, if the "basic" app sandbox configuration is broken in some large-scale way, then the entire system tends to fall apart. That dynamic makes large-scale problems hard to... miss.

Because of that, the assumption I'd start with here isn't "may app can't read/write its files", but is instead either:

  1. I'm trying to access the "wrong" place.

  2. "Something" external to my app is interfering with my app’s ability to function.

Expanding on that second point, it's important to remember that macOS is FAR more flexible/configurable than our other systems, which also means it's easier to "break" things. If you haven't already, the first thing I would do is verify that the problem happens on a "clean" configuration by testing on a newly installed system with nothing else installed. Particularly if you're working off of customer reports, it's very easy to waste a lot of time investigating a failure as a "bug" when the real problem is that a 3rd-party component is breaking your app.

If you've ruled out #2, then that leads to here:

Operation not permitted / NSCocoaErrorDomain Code=513: Permissions error when writing to disk. CFPrefsPlistSource: Path not accessible: Failure to write to UserDefaults. Cannot synchronize user defaults to disk: UserDefaults write blocked. CoreData: No permissions to create file: Core Data SQLite store can't be created. Firebase: Failed to open database: Firebase can't initialize local storage. CGDataConsumerCreateWithFilename: failed to open ... for writing: PDF generation fails due to temp directory access issues.

Looking over those error messages, the main thing I notice is that the messages are a mix of Apple and non-Apple logging. For example, nothing in the system ever logs "write blocked" or "Cannot synchronize user defaults to disk", so something else in your app logged that. I don't know what the specific issue might be, but the place I'd start here is by logging exactly what locations you're trying to access, then going to those location(s) to see what's actually there. I suspect what's actually happening is that you're trying to access a location that you don't have access to or which simply doesn't exist. As one concrete possibility:

...fails due to temp directory access issues

macOS and iOS both provide "tmp" and "Caches" directories, but the locations of those directories aren’t necessarily the same on both systems. If you retrieve those locations using APIs like NSTemporaryDirectory() or NSFileManager.url(for:in:appropriateFor:create:), then the system will give your app the correct location and everything will work fine. However, if you "get" to that location through some other means (for example, by starting with your container directory and building a path), then you can end up trying to interact with the wrong location.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thank you for your post. You mentioned that you created a focus sample demonstrating the issue. I recommend that you share this focus sample here to illustrate the problem.

If so, please share a link to your test project. That'll help us better understand what's going on. If you're not familiar with preparing a test project, take a look at Creating a test project.

Albert Pascual
  Worldwide Developer Relations.

Our app is unable to write to its own sandbox container on macOS when run via “My Mac (Designed for iPad)”. This is not an issue when the app runs on iPhone or on iPad.

So, the one thing to understand here is that the sandbox enforcement system operates at a low enough level of the system that I can't really "fail"*, at least not in a broad, systemic way. That's particularly true of apps running compatibility mode, which are designed to operate with very limited access.

*Putting that in more concrete terms, if the "basic" app sandbox configuration is broken in some large-scale way, then the entire system tends to fall apart. That dynamic makes large-scale problems hard to... miss.

Because of that, the assumption I'd start with here isn't "may app can't read/write its files", but is instead either:

  1. I'm trying to access the "wrong" place.

  2. "Something" external to my app is interfering with my app’s ability to function.

Expanding on that second point, it's important to remember that macOS is FAR more flexible/configurable than our other systems, which also means it's easier to "break" things. If you haven't already, the first thing I would do is verify that the problem happens on a "clean" configuration by testing on a newly installed system with nothing else installed. Particularly if you're working off of customer reports, it's very easy to waste a lot of time investigating a failure as a "bug" when the real problem is that a 3rd-party component is breaking your app.

If you've ruled out #2, then that leads to here:

Operation not permitted / NSCocoaErrorDomain Code=513: Permissions error when writing to disk. CFPrefsPlistSource: Path not accessible: Failure to write to UserDefaults. Cannot synchronize user defaults to disk: UserDefaults write blocked. CoreData: No permissions to create file: Core Data SQLite store can't be created. Firebase: Failed to open database: Firebase can't initialize local storage. CGDataConsumerCreateWithFilename: failed to open ... for writing: PDF generation fails due to temp directory access issues.

Looking over those error messages, the main thing I notice is that the messages are a mix of Apple and non-Apple logging. For example, nothing in the system ever logs "write blocked" or "Cannot synchronize user defaults to disk", so something else in your app logged that. I don't know what the specific issue might be, but the place I'd start here is by logging exactly what locations you're trying to access, then going to those location(s) to see what's actually there. I suspect what's actually happening is that you're trying to access a location that you don't have access to or which simply doesn't exist. As one concrete possibility:

...fails due to temp directory access issues

macOS and iOS both provide "tmp" and "Caches" directories, but the locations of those directories aren’t necessarily the same on both systems. If you retrieve those locations using APIs like NSTemporaryDirectory() or NSFileManager.url(for:in:appropriateFor:create:), then the system will give your app the correct location and everything will work fine. However, if you "get" to that location through some other means (for example, by starting with your container directory and building a path), then you can end up trying to interact with the wrong location.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Unable to write to file system when building for My Mac (Designed for iPad)
 
 
Q