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.

in my ~/Applications folder.

To be clear, you specifically meant:

<home directory>/Applications

...not the standard Applications directory? That's not actually one of our standard directories, which opens the possibility that the system "missed" the existence of the app, so it wasn't registered with LaunchServices. That shouldn't necessarily matter (you did tell the system where the app was...), but that would explain this:

Dang, now all of a sudden it's working.

If this was caused by a registration, then having this work:

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.

...would have also registered the app.

That leads to here:

Obviously I need to do a lot more testing.

As a general warning here, if you're going actively test this sort of thing, my recommendation would be to use VM. The problem here is that the architecture of LaunchServices means that its interactions with it tend to "self correct" problems. If your goal is to "capture" the system in a particular state, then you need to reproduce the problem, then preserve a copy of the system in that state so that you can test it again later.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

To be clear, you specifically meant:

<home directory>/Applications

...not the standard Applications directory? That's not actually one of our standard directories, which opens the possibility that the system "missed" the existence of the app, so it wasn't registered with LaunchServices.

The Launch Services Programming Guide says that

A built-in background tool, run whenever the system is booted or a new user logs in, automatically searches the Applications folders in the system, network, local, and user domains and registers any new applications it finds there.

The one in the user domain is ~/Applications. Also note that the Finder gives that one the standard Applications icon, whereas if you create an Applications folder in some random location, it gets a generic folder icon. So at least by some measures it is one of your standard directories.

I'll see if I can replicate in a VM.

@DTS Engineer It turns out that I cannot sign in to my Apple account within a macOS 26.1 VM. "Could not communicate with the server." So I can't test anything with iCloud Drive in a VM.

Oh, now I see why I couldn't use iCloud Drive in a 26.1 VM. The 26.1 release notes say "The serial number published for the virtual machine is 0, which prevents iCloud and related applications from functioning correctly. (163294564)".

Oh, now I see why I couldn't use iCloud Drive in a 26.1 VM.

I’m going to address this in the specific thread you created for it.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NSWorkspace openURL fails on file in iCloud Drive
 
 
Q