NSFileSandboxingRequestRelatedItemExtension: Failed to issue extension

Hi there,

I have an SwiftUI app that opens a user selected audio file (wave). For each audio file an additional file exists containing events that were extracted from the audio file. This additional file has the same filename and uses the extension bcCalls. I load the audio file using FileImporter view modifier and within access the audio file with a security scoped bookmark. That works well. After loading the audio I create a CallsSidecar NSFilePresenter with the url of the audio file. I make the presenter known to the NSFileCoordinator and upon this add it to the FileCoordinator. This fails with NSFileSandboxingRequestRelatedItemExtension: Failed to issue extension for; Error Domain=NSPOSIXErrorDomain Code=3 "No such process"

My Info.plist contains an entry for the document with NSIsRelatedItemType set to YES

I am using this kind of FilePresenter code in various live apps developed some years ago. Now when starting from scratch on a fresh macOS26 system with most current Xcode I do not manage to get it running. Any ideas welcome!

Here is the code:

struct ContentView: View {  
    @State private var sonaImg: CGImage?
    @State private var calls: Array<CallMeasurements> = Array()
    @State private var soundContainer: BatSoundContainer?
    
    @State private var importPresented: Bool = false
    
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
            if self.sonaImg != nil {
                Image(self.sonaImg!, scale: 1.0, orientation: .left, label: Text("Sonagram"))
            }
            if !(self.calls.isEmpty) {
                List(calls) {aCall in
                    Text("\(aCall.callNumber)")
                }
            }
            Button("Load sound file") {
                importPresented.toggle()
            }
        }
        .fileImporter(isPresented: $importPresented, allowedContentTypes: [.audio, UTType(filenameExtension: "raw")!], onCompletion: { result in
            switch result {
            case .success(let url):
                let gotAccess = url.startAccessingSecurityScopedResource()
                if !gotAccess { return }
                if let soundContainer = try? BatSoundContainer(with: url) {
                    self.soundContainer = soundContainer
                    self.sonaImg = soundContainer.overviewSonagram(expectedWidth: 800)
                    
                    let callsSidecar = CallsSidecar(withSoundURL: url)
                    let data = callsSidecar.readData()
                    print(data)
                }
                url.stopAccessingSecurityScopedResource()
            case .failure(let error):
                // handle error
                print(error)
            }
        })
        .padding()
    }
}

The file presenter according to the WWDC 19 example:

class CallsSidecar: NSObject, NSFilePresenter {
    lazy var presentedItemOperationQueue = OperationQueue.main
    var primaryPresentedItemURL: URL?
    var presentedItemURL: URL?
    init(withSoundURL audioURL: URL) {
        primaryPresentedItemURL = audioURL
        presentedItemURL = audioURL.deletingPathExtension().appendingPathExtension("bcCalls")
    }
    func readData() -> Data? {
        var data: Data?
        var error: NSError?
        
        NSFileCoordinator.addFilePresenter(self)
        let coordinator = NSFileCoordinator.init(filePresenter: self)
        NSFileCoordinator.addFilePresenter(self)
        coordinator.coordinate(readingItemAt: presentedItemURL!, options: [], error: &error) {
            url in
            data = try! Data.init(contentsOf: url)
        }
        return data
    }
}

And from Info.plist

<key>CFBundleDocumentTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeExtensions</key>
			<array>
				<string>bcCalls</string>
			</array>
			<key>CFBundleTypeName</key>
			<string>bcCalls document</string>
			<key>CFBundleTypeRole</key>
			<string>None</string>
			<key>LSHandlerRank</key>
			<string>Alternate</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>com.apple.property-list</string>
			</array>
			<key>LSTypeIsPackage</key>
			<false/>
			<key>NSIsRelatedItemType</key>
			<true/>
		</dict>
		<dict>
			<key>CFBundleTypeExtensions</key>
			<array>
				<string>wav</string>
				<string>wave</string>
			</array>
			<key>CFBundleTypeName</key>
			<string>Windows wave</string>
			<key>CFBundleTypeRole</key>
			<string>Editor</string>
			<key>LSHandlerRank</key>
			<string>Alternate</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>com.microsoft.waveform-audio</string>
			</array>
			<key>LSTypeIsPackage</key>
			<integer>0</integer>
			<key>NSDocumentClass</key>
			<string></string>
		</dict>
	</array>

Note that BatSoundContainer is a custom class for loading audio of various undocumented formats as well as wave, Flac etc. and this is working well displaying a sonogram of the audio.

Thx, Volker

I have a SwiftUI app that opens a user-selected audio file (wave). For each audio file, an additional file exists containing events that were extracted from the audio file. This additional file has the same filename and uses the extension bcCalls. I load the audio file using FileImporter view modifier and then access the audio file with a security-scoped bookmark. That works well.

To clarify here, do you mean that you’re able to access both the directly selected file and its related sidecar? Or just that you're able to access the direct file?

After loading the audio, I create a CallsSidecar NSFilePresenter with the URL of the audio file. I make the presenter known to the NSFileCoordinator and then add it to the FileCoordinator. This fails with NSFileSandboxingRequestRelatedItemExtension: Failed to issue extension for; Error Domain=NSPOSIXErrorDomain Code=3 "No such process"

Is the failure here about opening an existing file or about writing a new file? Also, what directory are you working out of?

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hello Kevin,

thx for coming here! Let me clarify:

I can only access the user selected file. The sidecar file can not be accessed, due to not getting a FilePresenter (Sandbox tells failed to issue an extension for file)

The files both user selected and sidecar reside in a folder inside my users document folder and I try to read the sidecar when the user opens the audio file.

I can access the sidecar file from terminal and load its content. I can also load its content when opening it with a second NSOpenPanel(). So access rights are okay. Using one of my Apps from the AppStore which implements the same file access works as well.

So currently I am lost why my fresh code on the fresh installed machine is not working.

TIA, Volker

The files, both user-selected and sidecar, reside in a folder inside my user’s document folder, and I try to read the sidecar when the user opens the audio file.

OK. SO, one thing I would test here is what happens if you test the same code with files that are in a directory "outside" of the normal user hierarchy. You can try with a directory inside your home directory, but I actually suggest using a folder ENTIRELY outside the user hierarchy— for example, on a disk image or an external volume.

The issue here is that macOS has multiple independent systems of data protection, most of which are focused on "user data" (like the contents of "~/Documents/"). Moving outside of that hierarchy means you’re looking at the "basic" case, which is easier to evaluate.

Looking at the other cases here:

I can access the sidecar file from the terminal and load its content.

FYI, Terminal.app is a tricky tool to test an experiment with. The issues here are:

  1. It's not sandboxed, which exempts it from the more aggressive file protection you’re dealing with here. This is mostly to avoid making you manually select which directories it has access to or using an entitlement to directly grant it broad access. However, this also means that it doesn't bypass the non-sandbox protections, which does have some security benefit.

  2. It's very easy to forget what actual access you've already given it. For example, it's very likely that you can list the contents of ~/Downloads, but that isn’t because it has special access. What actually happened is that at some previous point (weeks/months/years before) you tried accessing the directory and then approved the "Terminal.app is trying to access <directory>" dialog, which allowed later access. Many developers also grant it FDA (Full Disk Access), which bypasses most of these issues.

So access rights are okay. Using one of my apps from the App Store which implements the same file access works as well.

Was the App Store app the same app that created the sidecar file? I haven't looked into the details of this, but the quarantine data attached to the file also tracks what app(s) it interacts with, and we may be using that to validate access.

So currently I am lost as to why my fresh code on the fresh installed machine is not working.

So, what's tricky here is that there are lots of different protection mechanisms in place (see this post by Quinn for a good overview), which can make it very tricky to determine what's actually failing and why. The first thing I would actually do before spending too much time here is testing again with Developer ID signed build installed in "/Applications/". That's a "shipping" use case (which is what actually matters), so if that works, then you don't necessarily need to spend a lot of time figuring out EXACTLY what's going wrong.

Finally, on this point:

I can also load its content when opening it with a second NSOpenPanel().

First off, I think it's always a good idea to have a "backup" path in place for your users. It's very difficult to guarantee that something like this will "always" work, so the open panel serves as your backup plan to ensure that the user can always get things working no matter what happens.

In a similar vein, I'd also think about how you can tweak the user experience to sidestep these issues. For example, if you configure your sidecar files to be openable by your app, and your sidecar files include a document-scoped bookmark to its related file, then opening the sidecar gets you both files without relying on any special support from the system.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thank you a lot - I will try this weekend - I am at a client location right now - but when back I test and tell the results! Thanks a lot for the various ideas!

Best wishes, Volker

Thank you a lot - I will try this weekend - I am at a client location right now - but when back I test and tell the results! Thanks a lot for the various ideas!

Sounds good. Good luck and please let me know what you find.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hello Kevin, hello All

I have tested your suggestions. Sadly to no avail. The location of the files is not crucial nor using a signed version of the app.

I have also setup a new project on my macOS14 Mac with the same result. So it is not a macOS26 problem neither. That makes me wonder more and more.

My AppStore app (bcAnalyze) that does use the related file feature with these files works well on any macOS with these files. The code I am using is older dating back ca. 10 years (originated in Obj-C days and is now Swift since ca. 4 years). The idea of adding a security scoped bookmark to the sidecar file is tempting, but wouldn't help since the original application producing the the sidecar file is more than 10 years old and users may have already millions of file pairs.

There shouldn't be a difference between SwiftUi and AppKit as front-end, but I may also try this in the next days.

Since my AppStore app works, I must oversee something little that has this big effect. I can't otherwise explain the negative result. I have setup a super simple Git project here: https://github.com/vrunkel/RelatedFileTest

Background of these files / apps is: I am producing an automated bat detector since 2007. Since then a Mac app exists (now in its fourth major revision) that implements a bat call finder and saves results for each audio file in a so called bcCalls file containing a plist representation of call measurements. The app exists still outside the AppStore (signed and notarized) and I have roughly 1000 users. They record up to a couple of millions bat call recordings a year each.

When opening a folder and using the security scoped bookmark on the folder, I can load files. Since my app idea will be a document based app, that is not the perfect solution.

Thanks for any further pointers/ideas.

Have a nice week, Volker

NSFileSandboxingRequestRelatedItemExtension: Failed to issue extension
 
 
Q