NSFileManager copyItemAtURL:toURL:error: fails to give error when dstURL exists on 10.12.4

So, for a simple copy operation in my app, I use the follow NSFileManager method:


copyItemAtURL:toURL:error:


Since I retrieve the url from the pasteboard, there is a chance that the source URL is already at the destination directory in my app (that is, user copies the file in another app maybe, then does paste in my app, so srcURL and dstURL is the same). In that case, I didn't really care because I gracefully handle the file exists error, rather then preemptively checking if fileExistsAtPath before attempting the copy.


Now it seems on 10.12.4 NSFileManager copyItemAtURLtoURL: returns YES even if the file exists and gives me no error to handle. At first I thought I made some code change that caused this in between app versions because on the live version of my app my error handling code seems to be working (on 10.12.4). So I looked and my commit history but came up with no changes to this code.


But for whatever reason when compiliing on 10.12.4 I don't get an error to handle in this case. I'm still on Xcode 8.2.1.


I looked to see if any changes was documented in the release notes, but I don't see anything?


Stepped right through it in the debugger....method returns YES and the macOS logs out


open on /Users/UserName/FilePathHere File exists


But why don't I get an error to handle anymore? 😕

Replies

heh, I filed a bug.


31580982


Also tried setting myself as the NSFileManager delegate to see if the following method gets called:


- (BOOL)fileManager:(NSFileManager *)fileManager shouldProceedAfterError:(NSError *)error copyingItemAtURL:(NSURL *)srcURL toURL:(NSURL *)dstURL



But it does not. If this ends up getting closed as intended behavior, my hope is that Apple considers at least documenting changes in behavior that are likely to break app functionalithy....especially on minor version releases. It seems unreasonable for an operation that fails to return YES as if it has succeeded. I swear if I get a nasty response I'm gonna' flip.

>> preemptively checking if fileExistsAtPath before attempting the copy


You are correct to not do this, for the reason you said (there's a race condition after you check but before you copy where the result of the check is unreliable).


>> on 10.12.4 NSFileManager copyItemAtURLtoURL: returns YES even if the file exists and gives me no error to handle


Yes, I was able to verify this misbehavior on 10.12.4 (using Xcode 8.3.1, but I doubt that this matters). It appears to be a pretty nasty bug.


>> preemptively checking if fileExistsAtPath before attempting the copy


But this might be the best workaround for now. It doesn't actively do any harm (since the subsequent code does handle errors properly, when they are returned), and falling foul of the race condition is statistically unlikely.

I'm actually now kind of scared to ship this update because my app uses NSFileManager in many places. If they made changes that breaks error handling in NSFileManager (besides the one I just caught), my app could be in for a world of hurt.

You should at least wait a few days, because sometimes you'll get feedback when your bug report is initially triaged, and that typically doesn't take more than a couple of days.


What happens when you run your old release on 10.12.4? If you engineer a scenario where it tries to copy over an existing file, does it report the error or just fail with the log message?

When I run the version of the app that is live now, I get the error even on 10.12.4 and my app handles it. This made me think that I made a dumb change somewhere in my code since the last version.


So I was digging through my commit logs. But the last time I changed the code responsible for this functionality was well before the last time I updated the app.

>But this might be the best workaround for now. It doesn't actively do any harm (since the subsequent code does handle errors properly, when they are returned), and falling foul of the race condition is statistically unlikely.


Yeah...to keep the code cleaner (but not clean) I'd probably subclass and override it, and set the error that should be set myself...or add a category method. I'm not exactly thrilled about having to do this. I should have left one of my Macs on 10.12.3.


I could write a bunch of tests to try to see what errors (if any more other than this) aren't being given back to me proper. But I'm an indy developer and I don't have the time. How much do devs have to give to Apple, by way of bug reports, hardware purchases, and 30% of App Sales before they start giving developers something back (besides the ones who "juiced in"). 😢


I will accept a donation in good faith.

My bug got closed as a dupe.

The same happens on iOS 10.3.1. Looks like multiplatform regression.

We just re-reported this same issue - we noticed, however, that the problem - copyItemAtPath/copyItemAtURL returning YES when it should have said NO - only occurs when running under LLDB. When we run the same binary directly from Terminal, copyItemAtPath does return NO as it should. This behavior is consistent beginning with 10.12.4 through at least 10.12.6 beta (16G8c).

I see now that the method also returns YES when there's a permissions error (logs out Operation not permitted) but returns YES and fails. I'm on 10.12.5.

Interesting. Recently we pressed them to ask if there was any news on this issue*, and they indicated that they were working on it and would keep us posted.


*I actually had to attach LLDB to our running app to shoot something unrelated, and I may have seen some weird returns in the trace, this time from moveItemAtPath - but we're chasing several other dragons right now, I had no time to stop & gawk.