FSKit module mount fails with permission error on physical disks

I'm trying to make an FSKit module for NTFS read-write filesystem and at the stage where everything is more or less working fine as long as I mount the volume via mount -F and that volume is a RAM disk. However, since the default NTFS read-only driver is already present in macOS, this introduces an additional challenge.

Judging by the DiskArbitration sources, it looks like all FSKit modules are allowed to probe anything only after all kext modules. So, in this situation, any third-party NTFS FSKit module is effectively blocked from using DiskArbitration mechanisms at all because it's always masked during the probing by the system's read-only kext.

This leaves mount -F as the only means to mount the NTFS volume via FSKit. However, even that doesn't work for volumes on real (non-RAM) disks due to permission issues. The logs in Console.app hint that the FSKit extension is running; however, it looks like the fskitd itself doesn't have permissions to access real disks if it's initiated from the mount utility?

default	16:42:41.939498+0200	fskitd	New module list <private>
default	16:42:41.939531+0200	fskitd	Old modules (null)
default	16:42:41.939578+0200	fskitd	Added 2 identifiers: <private>
default	16:42:41.939651+0200	fskitd	[0x7fc58020bf00] activating connection: mach=true listener=true peer=false name=com.apple.filesystems.fskitd
debug	16:42:41.939768+0200	fskitd	main:RunLoopRun
debug	16:42:41.939811+0200	fskitd	-[liveFilesMountServiceDelegate listener:shouldAcceptNewConnection:]: start
default	16:42:41.939870+0200	fskitd	Incomming connection, entitled 0
debug	16:42:41.940021+0200	fskitd	-[liveFilesMountServiceDelegate listener:shouldAcceptNewConnection:]: accepting connection
default	16:42:41.940048+0200	fskitd	[0x7fc580006120] activating connection: mach=false listener=false peer=true name=com.apple.filesystems.fskitd.peer[1816].0x7fc580006120
default	16:42:41.940325+0200	fskitd	Hello FSClient! entitlement no
default	16:42:41.940977+0200	fskitd	About to get current agent for 503
default	16:42:41.941104+0200	fskitd	[0x7fc580015480] activating connection: mach=true listener=false peer=false name=com.apple.fskit.fskit_agent
info	16:42:41.941227+0200	fskitd	About to call to fskit_agent
debug	16:42:42.004630+0200	fskitd	-[fskitdAgentManager currentExtensionForShortName:auditToken:replyHandler:]_block_invoke: Found extension for fsShortName (<private>)
info	16:42:42.005409+0200	fskitd	Probe starting on <private>
debug	16:42:42.005480+0200	fskitd	-[FSResourceManager getResourceState:]:not_found:<private>
debug	16:42:42.005528+0200	fskitd	-[FSResourceManager addTaskUUID:resource:]:<private>: Adding task (<private>)
debug	16:42:42.005583+0200	fskitd	applyResource starting with resource <private> kind 1
default	16:42:42.005609+0200	fskitd	About to get current agent for 503
info	16:42:42.005629+0200	fskitd	About to call to fskit_agent
debug	16:42:42.006700+0200	fskitd	-[fskitdXPCServer getExtensionModuleFromID:forToken:]_block_invoke: Found extension <private>, attrs <private>
default	16:42:42.006829+0200	fskitd	About to get current agent for 503
info	16:42:42.006858+0200	fskitd	About to call to fskit_agent, bundle ID <private>, instanceUUID <private>
default	16:42:42.070923+0200	fskitd	About to grab assertion on pid 1820
default	16:42:42.071058+0200	fskitd	Initializing connection
default	16:42:42.071141+0200	fskitd	Removing all cached process handles
default	16:42:42.071185+0200	fskitd	Sending handshake request attempt #1 to server
default	16:42:42.071223+0200	fskitd	Creating connection to com.apple.runningboard
info	16:42:42.071224+0200	fskitd	Acquiring assertion: <RBSAssertionDescriptor| "com.apple.extension.session" ID:(null) target:1820>
default	16:42:42.071258+0200	fskitd	[0x7fc58001cdc0] activating connection: mach=true listener=false peer=false name=com.apple.runningboard
default	16:42:42.075617+0200	fskitd	Handshake succeeded
default	16:42:42.075660+0200	fskitd	Identity resolved as osservice<com.apple.filesystems.fskitd>
debug	16:42:42.076337+0200	fskitd	Adding assertion 183-1817-1669 to dictionary
debug	16:42:42.076385+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]:bsdName:<private>
default	16:42:42.076457+0200	fskitd	[0x7fc5801092e0] activating connection: mach=true listener=false peer=false name=com.apple.fskit.fskit_helper
default	16:42:42.077706+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]_block_invoke: Open device returned error Error Domain=NSPOSIXErrorDomain Code=13
info	16:42:42.077760+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]: failed to open device <private>, Error Domain=NSPOSIXErrorDomain Code=13
default	16:42:42.077805+0200	fskitd	[0x7fc5801092e0] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
debug	16:42:42.077830+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]:end
info	16:42:42.078459+0200	fskitd	openWith returned err Error Domain=NSPOSIXErrorDomain Code=13 dev (null)
error	16:42:42.078501+0200	fskitd	-[fskitdXPCServer getRealResource:auditToken:reply:]: Unable to convert proxy FSBlockDeviceResource into open resource
error	16:42:42.078538+0200	fskitd	-[fskitdXPCServer applyResource:targetBundle:instanceID:initiatorAuditToken:authorizingAuditToken:isProbe:usingBlock:]: Can't get the real resource of <private>
default	16:42:42.105443+0200	fskitd	[0x7fc580006120] invalidated because the client process (pid 1816) either cancelled the connection or exited

The mount utility call I use is the same for RAM and real disks with the only difference being the device argument and this permission error is only relevant for real disks case.

So, the proper solution (using DiskArbitration) seems to be blocked architecturally in this use case due to FSKit modules being relegated to the fallback role. Is this subject to change in the future?

The remaining workaround with using the mount directly doesn't work for unclear reasons. Is that permission error a bug? Or am I missing something?

However, since the default NTFS read-only driver is already present in macOS, this introduces an additional challenge.

Please file a bug about this specific case (system r/o NTFS driver blocks r/w FSKit driver) and then post that bug number back here. While the basic behavior (prioritizing KEXTs over FSKit) is reasonably justifiable and difficult to address, I think the specific issue around r/o NTFS is important (and narrow) enough that we might want to consider a special cased solution.

So, the proper solution (using DiskArbitration) seems to be blocked architecturally

Note that there is also a bug in DiskArb that is preventing FSKit volumes from working correctly. See this thread for more details.

This leaves mount -F as the only means to mount the NTFS volume via FSKit.

You might also try including "-t nontfs". I haven't tried it, but I believe that would exclude the kernel NTFS driver while leaving yours as an option.

However, even that doesn't work for volumes on real (non-RAM) disks due to permission issues.

A few things here:

  1. You ran "mount" as root, correct?

  2. Is the slice you're trying to target on the boot device or is it an external volume?

  3. Are you able to mount disk images?

The remaining workaround with using the mount directly doesn't work for unclear reasons. Is that permission error a bug? Or am I missing something?

I'm not sure. It's possible that the boot volume is special cased, but other devices should work. Similarly, disk images bypass most of the permission dynamics that effect physical devices. Finally, I'm not sure how the NTFS collision changes things.

The big thing to look at here is what the large system log shows, particularly between these log messages:

debug	16:42:42.076385+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]:bsdName:<private>
default	16:42:42.076457+0200	fskitd	[0x7fc5801092e0] activating connection: mach=true listener=false peer=false name=com.apple.fskit.fskit_helper
default	16:42:42.077706+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]_block_invoke: Open device returned error Error Domain=NSPOSIXErrorDomain Code=13

That sequence called out to "fskit_helper" and I'd expect there to be logging from it or secondary components that might provide more detail on the underling issue.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Please file a bug about this specific case (system r/o NTFS driver blocks r/w FSKit driver) and then post that bug number back here.

I have filed a bug: FB18230524

You might also try including "-t nontfs". I haven't tried it, but I believe that would exclude the kernel NTFS driver while leaving yours as an option.

It looks like mount (without -F) tries to use literal non-existent nontfs filesystem in this case:

$ mount -t nontfs disk2s2 ./mnt
mount: exec /Library/Filesystems/nontfs.fs/Contents/Resources/mount_nontfs for /Users/user/temp/fstest/mnt: No such file or directory
mount: /Users/user/temp/fstest/mnt failed with 72

You ran "mount" as root, correct?

I currently run mount as a normal administrator user (otherwise this workaround would need a helper with elevated privileges to be used in the app). However, I also attempted to run it as root. In that case the mount -F command fails without providing a specific error message.

$ sudo mount -F -t abcd_ntfs disk11 ./mnt
mount: Unable to invoke task

# mount -F -t abcd_ntfs disk11 ./mnt
mount: Unable to invoke task

Judging by the logs, it stops somewhere early:

default	16:54:13.664228+0200	fskitd	Hello FSClient! entitlement no
default	16:54:13.664465+0200	mount	Setting remote protocol to all XPC
default	16:54:13.665000+0200	fskitd	Getting own modules
default	16:54:13.665045+0200	fskitd	Returning module array <private>
default	16:54:13.665236+0200	mount	[0x7fe9e1a04140] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
default	16:54:13.665266+0200	fskitd	[0x7f9424a05570] invalidated because the client process (pid 1542) either cancelled the connection or exited

Furthermore, the mount -F command fails for all volumes when run with root privileges, including non-physical volumes.

Is the slice you're trying to target on the boot device or is it an external volume?

I have tested both a volume on the boot device and an external volume on a USB device. In both cases, the same error occurs and almost identical logs:

$ mount -F -t abcd_ntfs disk2s2 ./mnt
mount: Probing resource: The operation couldn’t be completed. Permission denied
mount: Unable to invoke task

Are you able to mount disk images?

Yes, disk images can be mounted without issues using the non-root mount -F command.

$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount ./ntfs-rw.dmg
/dev/disk11
$ mount -F -t abcd_ntfs disk11 ./mnt
$ diskutil info disk11
   Device Identifier:         disk11
   Device Node:               /dev/disk11
   Whole:                     Yes
   Part of Whole:             disk11
   Device / Media Name:       Disk Image

   Volume Name:               NTFS_IMAGE
   Mounted:                   Yes
   Mount Point:               /Users/user/temp/fstest/mnt

Finally, I'm not sure how the NTFS collision changes things.

Just in case, the filesystem short name in my FSKit module is not ntfs/NTFS to avoid the naming collision.

The big thing to look at here is what the large system log shows, particularly between these log messages:

I have attached fuller log of that area.

I also encountered this permission issue when working with FSKit on physical external volume (e.g. a USB device). The workaround I'm using is to change the owner of the dev node to be the current user:

sudo chown $(whoami) /dev/rdisk6s3

(where disk6s3 is your target disk)

This probably isn't a great long-term solution but it at least got me able to test my module with a physical device.


(Running mount as root didn't work for me either. It's as if it didn't know the FSKit module was there. My assumption was that enabling the module in Settings only enabled it for my user account, and root didn't have it enabled? I suppose based on @DTS Engineer 's suggestion to run mount as root, sudo mount not working is actually a bug though.)

I also encountered this permission issue when working with FSKit on physical external volume (e.g. a USB device). The workaround I'm using is to change the owner of the dev node to be the current user:

Unfortunately, more bugs have been found so you're going to need to wait for more fixes. Thanks for your patience and I'll try and let you know when you should test again.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Same root cause we worked around in TestFS — sharing data and our fix in case it helps

We hit this on macOS 26.4.1 in a third-party FSKit V1 block-resource extension shipped via a Sparkle-auto-updated host app (com.sohonet.testfsmount.appex inside TestFS.app). Reproducible cycle:

  1. Fresh install: mount works.

  2. Auto-update replaces /Applications/TestFS.app.

  3. System Settings → Login Items & Extensions → File System Extensions still reads "TestFS — on."

  4. mount(8) -F -t testfs /dev/diskN /tmp/foo fails:

    mount: Loading resource: The operation couldn't be completed.
           (com.apple.extensionKit.errorDomain error 2.)
    mount: File system named testfs not found
    

    mount(8) exits 69 (EX_UNAVAILABLE).

  5. Toggling the System Settings switch off and then back on always fixes it. So does waiting some unspecified amount of time, or invoking mount(8) against a different /dev/diskN after a fresh hdiutil attach cycle (apparently triggers re-resolution).

Reading lsd and extensionkitservice logs against the same time window suggests lsd re-registers the appex with a new internal UUID after the bundle replacement, but extensionkitservice keeps a handle to the previous UUID, so the lookup-by-fstype fails until something forces re-adjudication.

Workaround that's working for us

On every app launch, we compare the running CFBundleVersion against a stored value in UserDefaults. If they differ (i.e. the app was just replaced — first launch in the new bundle), we shell out to:

/System/.../LaunchServices.framework/.../lsregister -f /Applications/TestFS.app
/usr/bin/pluginkit -a /Applications/TestFS.app/Contents/Extensions/TestFSExtension.appex

…then save the new version. Subsequent launches with the same version skip the re-register. Net effect: by the time the user clicks Mount, extensionkitd has already re-resolved the new bundle.

This is the same workaround macFUSE 5.2.0 release notes describe shipping for the same class of issue: https://macfuse.github.io/2026/04/09/macfuse-5.2.0.html

Things I'd love to know from Apple

  • Is lsregister -f + pluginkit -a from inside the just-launched .app the right approach, or are we masking a deeper bug we should be filing instead?
  • Is there an FSKit / ExtensionKit API we should be calling on launch ("force re-adjudication") rather than shelling to CLI tools?
  • Does Apple have an internal radar already tracking the lsd / extensionkitservice UUID-mismatch story? Happy to add a fresh Feedback Assistant report if helpful — would just rather link to the existing one if one exists.

Source repo: https://github.com/sohonetlabs/testfs (workaround in AppEnvironment.reregisterExtensionIfNeeded() if anyone wants to copy the pattern).

@ben_roeder I don't think that is the same issue as what was originally described, and I'm not Apple, but I have seen something similar, although I reproduced it after rebuilding the app with Xcode (FB22516139). Maybe this is what you're hitting. I checked the status on my feedback about that and it says a fix is coming in a future OS update, although I'm not sure specifically which beta version, if any, currently has the fix.

Is lsregister -f + pluginkit -a from inside the just-launched .app the right approach?

Well, no. None of this should be necessary, as the system should be taking care of it.

Having said that, I don't really have any objection to it as a workaround. Both of those commands are performing operations that the system would have/should done anyway, so there isn't a lot that can go wrong. In a similar vein:

Is there an FSKit / ExtensionKit API we should be calling on launch ("force re-adjudication") rather than shelling to CLI tools?

No, and I wouldn't really want/expect us to add one. There are situations where:

  • The work being done is complex and involves multiple layers of the system.

  • The required inputs are straightforward for the caller to determine independent of the request.

  • We independently have/need a command line tool.

...in which case it's often better to simply rely on the command line tool instead of creating a public API.

or are we masking a deeper bug we should be filing instead?

...and, yes, you should absolutely file a bug on this.

Does Apple have an internal radar already tracking the lsd / extensionkitservice UUID-mismatch story?

I believe we do, but don't have the number immediately at hand. In any case, please file a bug on this and post the bug number back here so I can make sure it gets where it needs to be.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

FSKit module mount fails with permission error on physical disks
 
 
Q