Restore Clean NSFileProviderReplicatedExtension Environment

While developing and porting macOS file provider extensions based on NSFileProviderReplicatedExtension I sometimes ended up in a messed up state of my environment. I found these steps to restore a clean environment again.

As I do not know everything about the file provider framework and its internals on macOS this information cannot be considered exhaustive. However there is a good change it already is sufficient for you, too. I will update this post in case I find out any additional cleanup steps.

As I read from communication with Apple through technical support incidents the rapid development cycle of building, registering, running, setting up, unregistering, deleting file providers can lead to hiccups in the development environment. In example: There is some XPC involved when using NSFileProviderManager and sometimes the newly built file provider extensions are not loaded yet which leads to any operation with file provider domains throwing fatal errors. The famous “Have you tried turning it off and on again?” gives away a possible solution which worked often. It becomes annoying, though, if it has to be done too often. And sometimes it does help at all. The problem must be something else. Subjectively, it has become more reliable and smooth after updating to macOS 13 Ventura.

Removing the File Provider Domain

I learned about the fileproviderctl program in macOS only through a technical support incident I issued. It has become an essential tool I use often and daily in my routine. In opposite to the more generic pluginkit program it provides information about file providers in a much more detailed way. The latter is complementary and useful to check whether the extension is found and loaded in general.

Because file providers are not just a bunch of files and folders in the file system but a bit more complicated system of frameworks, daemons and state sprinkled across here and there it is better to delegate removal to dedicated tools instead of brute culling file system items. The appropriate terminal command is this:

fileproviderctl domain remove <insert-your-provider-identifier-here>

This cleans up the local state of your file provider domain which manifestes as a directory in ~/Library/CloudStorage. With super user privileges you can also apply the brute force of rm -rf there but let’s rather not out of caution. Those directories are not removed when you disable or remove the file provider extension or complete host app. As with traditional file synchronization clients, this is like the synchronized root folder. You can delete your client app but it does not necessarily affect your locally available files. If your work-in-progress file provider extension code messed up your local state and you want to start over again, this has to be cleaned up.

Removing Application Data

There are bunch of directories which need or can be deleted to get rid of settings as well. Note: this highly depends on what your app does. The directories listed below are just typical standard paths for user defaults or CoreData.

~/Library/Containers/<app-bundle-identifier> # in example:
~/Library/Group Containers/<group-bundle-identifier> # in example:
~/Library/Application Support/FileProvider/<app-bundle-identifier><provider-suffix> # in example:

Out of caution I intentionally did not write recursive deletion commands to copy and paste.

Killing User Defaults Daemon

I do not remember when or where but I read that in some macOS release some years ago a daemon was introduced to cache user default values. To ensure no cached values are retrieved from that daemon even though the persisted user defaults have been obliterated from storage it can be killed.

killall cfprefsd

Killing File Provider Daemon

The same treatment can be applied to fileproviderd. I ocassionally observed some effect of doing this during development.

killall fileproviderd

It is restarted automatically afterwards.

Stumbling Block IBDesignables

At one point during development I observed two kinds of problems:

  1. The debugger apparently stepping through the code of an older build because the lines did not match the cursor.
  2. The main app shipping the file provider extension always received errors from NSFileProviderManager when trying to do anything with file provider domains.

After asking for some information about the file provider state through fileproviderctl like in the following snippet I saw the extension was loaded from somewhere in Xcode’s derived data directory.

fileproviderctl dump <provider-identifier>

To my surprise from a different location than the usual of debug build products. It came from a cache for IBDesignables. As you maybe know, Xcode builds targets for IBDesignables when a storyboard is opened for editing in Xcode. This also means that my app was build as it is during debugging with Xcode. Including the file provider extension. And the eager extension system on macOS registers and loads such extensions from wherever it may find them, including the trash. So, somehow an apparently outdated build of my extension was loaded by the system from the wrong location. In my case I had no business to do with the storyboard for now. Hence I closed it and deleted the cached derived data which included the builds for IBDesignables.

About The Author

Peter Thomas Horn is a professional software developer at Open-Xchange specialized on the Apple platform. He previously worked a decade across the full stack of various web technologies. Originally started with Java on Windows at the age of 12 years. While staying humble in throwing around buzzwords like "VR" and "machine learning" he occasionally experiences problems and the fitting solutions considered worth sharing.