NSWorkspace openURL fails on file in iCloud Drive

When I pass a file path url of a file in iCloud Drive to -[NSWorkspace openURLs:withApplicationAtURL:configuration:completionHandler:], it fails. There is no exception, and the completion handler isn't called. This is in a sandboxed app on macOS 26.1.

NSWorkspaceOpenConfiguration* config = NSWorkspaceOpenConfiguration.configuration;
config.activates = YES;
config.promptsUserIfNeeded = YES;
NSLog(@"performDrag 2 with %@", filePathObs);
[NSWorkspace.sharedWorkspace
    openURLs: filePathObs
    withApplicationAtURL: appURL
    configuration: config
    completionHandler:
        ^(NSRunningApplication * _Nullable app, NSError * _Nullable error)
        {
            NSLog(@"performDrag 3");
            if (error != nil)
            {
                NSLog(@"%@\n%@", error, filePathObs);
            }
            NSLog(@"complete performDrag");
        }];
NSLog(@"performDrag 4");

In the debug log, the performDrag 2 and performDrag 4 messages appear.

I also looked in the Console log, but the only messages that mention my app don't mean anything to me.

AFIsDeviceGreymatterEligible Missing entitlements for os_eligibility lookup
6c Reentrant message: kDragIPCCompleted, current message: kDragIPCLeaveApplication
Answered by DTS Engineer in 868267022

When I pass a file path URL of a file in iCloud Drive to -[NSWorkspace openURLs:withApplicationAtURL:configuration:completionHandler:], it fails.

A few different suggestions/questions:

  • Have you tried this with different apps and, ideally, using a dedicated test app as the target?

  • Related to that point, what happens if you use "open" (which basically does exactly what you're doing) to do the same thing? Note that I'm NOT suggesting you use "open" instead of NSWorkspace, just trying to clarify if the failure is specific to your app or not:

open <file path> -a <app path>
  • How did your app "get" that file URL? Is your app able to open the file? And is the file already downloaded or is it still dataless?

  • Is the target path in "/Applications/" or somewhere else? If it's not in "/Applications/", does your app have access to the location it's located at?

Covering a few details:

There is no exception, and the completion handler isn't called.

I'd have to look at the code, but I suspect the completion handler is tied into the AppleEvent sequence that's triggering the open. I think that means that the "right" kind of failure might cause the completionHandler to never be called.

I also looked in the Console log, but the only messages that mention my app don't mean anything to me.

Those messages look like log noise, but the bigger issue is that the "interesting" messages aren't going to come from your app and may not directly reference your app at all. To look at this from the Console side, here is what I would do:

  • Start with the "simplest" system configuration you can possibly make. At a minimum, that means quitting everything except your test app, but ideally I'd use a dedicated test system that was minimally configured. As you've noticed, there is an enormous amount of log noise, so the trick is to reduce that noise by making the machine do "less".

  • Make sure all of your app logs are written to the console log as well, as they provide the "index" that tells you where to start looking.

  • Reproduce the issue, then either trigger a sysdiagnose or use the instructions here to collect a console archive. Don't try and work out of the "live" Console.app, as it's too easy to lose data.

Once you've got the log, start by finding your "performDrag 2" log message. That's your starting point, since you know whatever went wrong happened "after" that point. Shortly after that point, you'll find logging from the system daemon (probably launchservicesd) that are actually doing the "work" of processing your request. If you watch what that daemon logs, I suspect you'll find the problem, though following the issue may require "jumping" to other daemons as the work is moved between processes. Two other suggestions here:

  1. Do the same testing and analysis, but with a file that works correctly. That case will also print "performDrag 3", which means the relevant logging will be "between" your 2 & 3 log messages. The working case will show you what the log "should" look like, which can make it easier to see where things change/go wrong.

  2. Look for both the file path and the target app in the log, not just your app, then look at what the logging "around" those log messages says, not just the immediate log messages.

(this came in after I'd already written most of this)

P.S., I find that if I instead use the ancient but not deprecated function LSOpenFromURLSpec, then it works. So at least I have a workaround.

Huh. That's actually quite strange, as NSWorkspace is going through LaunchServices as well (it actually used to call LSOpenFromURLSpec), just using new asynchronous API. Just to clarify, the issue here is that "nothing" (no app launch and/or document open) is happening, not just that the completion isn't being called?

If the issue is that the completion isn't being called, then my question is what thread are you calling that code on? The main thread or a secondary thread? If you're off the main thread, particularly in a GCD block? Does it work if you call it from the main thread?

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

P.S., I find that if I instead use the ancient but not deprecated function LSOpenFromURLSpec, then it works. So at least I have a workaround.

When I pass a file path URL of a file in iCloud Drive to -[NSWorkspace openURLs:withApplicationAtURL:configuration:completionHandler:], it fails.

A few different suggestions/questions:

  • Have you tried this with different apps and, ideally, using a dedicated test app as the target?

  • Related to that point, what happens if you use "open" (which basically does exactly what you're doing) to do the same thing? Note that I'm NOT suggesting you use "open" instead of NSWorkspace, just trying to clarify if the failure is specific to your app or not:

open <file path> -a <app path>
  • How did your app "get" that file URL? Is your app able to open the file? And is the file already downloaded or is it still dataless?

  • Is the target path in "/Applications/" or somewhere else? If it's not in "/Applications/", does your app have access to the location it's located at?

Covering a few details:

There is no exception, and the completion handler isn't called.

I'd have to look at the code, but I suspect the completion handler is tied into the AppleEvent sequence that's triggering the open. I think that means that the "right" kind of failure might cause the completionHandler to never be called.

I also looked in the Console log, but the only messages that mention my app don't mean anything to me.

Those messages look like log noise, but the bigger issue is that the "interesting" messages aren't going to come from your app and may not directly reference your app at all. To look at this from the Console side, here is what I would do:

  • Start with the "simplest" system configuration you can possibly make. At a minimum, that means quitting everything except your test app, but ideally I'd use a dedicated test system that was minimally configured. As you've noticed, there is an enormous amount of log noise, so the trick is to reduce that noise by making the machine do "less".

  • Make sure all of your app logs are written to the console log as well, as they provide the "index" that tells you where to start looking.

  • Reproduce the issue, then either trigger a sysdiagnose or use the instructions here to collect a console archive. Don't try and work out of the "live" Console.app, as it's too easy to lose data.

Once you've got the log, start by finding your "performDrag 2" log message. That's your starting point, since you know whatever went wrong happened "after" that point. Shortly after that point, you'll find logging from the system daemon (probably launchservicesd) that are actually doing the "work" of processing your request. If you watch what that daemon logs, I suspect you'll find the problem, though following the issue may require "jumping" to other daemons as the work is moved between processes. Two other suggestions here:

  1. Do the same testing and analysis, but with a file that works correctly. That case will also print "performDrag 3", which means the relevant logging will be "between" your 2 & 3 log messages. The working case will show you what the log "should" look like, which can make it easier to see where things change/go wrong.

  2. Look for both the file path and the target app in the log, not just your app, then look at what the logging "around" those log messages says, not just the immediate log messages.

(this came in after I'd already written most of this)

P.S., I find that if I instead use the ancient but not deprecated function LSOpenFromURLSpec, then it works. So at least I have a workaround.

Huh. That's actually quite strange, as NSWorkspace is going through LaunchServices as well (it actually used to call LSOpenFromURLSpec), just using new asynchronous API. Just to clarify, the issue here is that "nothing" (no app launch and/or document open) is happening, not just that the completion isn't being called?

If the issue is that the completion isn't being called, then my question is what thread are you calling that code on? The main thread or a secondary thread? If you're off the main thread, particularly in a GCD block? Does it work if you call it from the main thread?

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

@DTS Engineer Thank you for the detailed reply! It may take me a while to respond to all of your points, but here is a start:

  • Yes, the issue here is that "nothing" (no app launch and/or document open) is happening.
  • The target app is a copy of BBEdit in my ~/Applications folder.
  • Using the open command to open the same text file with the same copy of BBEdit works fine.
  • Regarding "How did your app "get" that file URL? Is your app able to open the file? And is the file already downloaded or is it still dataless?" The file is downloaded. My app gets the URL by drag and drop from the Finder. My app does not attempt to open the file on its own, it just forwards the URL to be opened by another app, BBEdit in this case, somewhat like what the Dock does.

Dang, now all of a sudden it's working. Obviously I need to do a lot more testing.

NSWorkspace openURL fails on file in iCloud Drive
 
 
Q