NSURLSession downloads to inaccessible file

I'm using an NSURLSession for background downloads, and even though the download is apparently successful, didFinishDownloadingToURL is giving a URL that the app doesn't have permission to access. An example:


/var/mobile/Library/Caches/com.apple.nsurlsessiond/Downloads/com.company.appname/CFNetworkDownload_u0dx1W.tmp


Usually, downloads are successful. In that case, the URL from didFinishDownloadingToURL looks like this:


/private/var/mobile/Containers/Data/Application/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx/Library/Caches/com.apple.nsurlsessiond/Downloads/com.company.appname/CFNetworkDownload_u0dx1W.tmp

The big problem is that once I start getting bad URLs, nsurlsessiond seems to be stuck in that state. Failures continue even after rebooting the device or deleting and reinstalling the app. I've observed this problem with iOS 10.2 and the iOS 10.3 betas. Has anyone seen something similar and found a workaround? This really looks to me like an iOS bug.


—Chris

This really looks to me like an iOS bug.

Indeed it does. Please file a bug about this, including all the diagnostic info you have so far, then post your bug number just for the record.

Also, once you’ve filed the bug please send me the bug number via email (my individual email address is in my signature).

Has anyone seen something similar and found a workaround?

I’ve not seen this before but the standard workaround for persistent problems like this is to invalidate the session (

-invalidateAndCancel
) and then try again with a new session. In my experience that clears most persistent NSURLSession background session problems.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you for the response and the suggestion. I filed a bug report a few days ago and just emailed you the bug number.


—Chris

Thank you for the quick reply, Quinn.


invalidateAndCancel didn't seem to help. However I did find an apparent workaround... Our app has a few extensions. None of these actually need to access our downloaded content, but just on the off-chance it might help, I decided to assign the sharedContainerIdentifier of the URL session. Once I did that, all file downloads started succeeding. I've verified that the problem (which was persistent across device reboots and app delete/reinstallation) is now fixed on two devices.


As long as we don't see further missing file problems, this is a completely satisfactory workaround for us. Still, it seems that is shouldn't be necessary to set the sharedContainerIdentifier for the main app when the app doesn't need to have the downloaded content available to the extensions.


—Chris

We're having the same issue with a watchOS project. invalidateAndCancel doesn't work either. And setting the sharedContainerIdentifier helped initially but the error keeps coming back on multiple devices after a while. Then the URLSession seems to produce only inaccessible files - even after a reboot.


When leaving the app unopened for a few days/a week the issue seems to vanish - which is odd. And also a factory reset (and restore from backup) of the Watch seems to temporarily fix the issue.


We've filed a bug with the ID 36102866 (rdar://36102866)

I had reason to look at this in depth on behalf of another developer and my conclusion is that this is most definitely a bug in

NSURLSession
. We have a ‘lead’ bug for this (r. 32534132) and I’ve made sure to mark the bugs mentioned in this thread as related to that one.

This problem is still being investigated by

NSURLSession
engineering. Alas, I have no estimate as to when it might be fixed.

I searched long and hard for a reliable workaround for this, but was unable to find one. The

-invalidateAndCancel
trick helps with some problems like this, but not this problem. Deleting the app from the device then restarting the device will clear some, but not all, occurrences of this problem.

I’m sorry I don’t have better news here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

This bug happens again, but this time is in app which is signed with enterprise certificate that running on iOS13.


The file we download will always downloaded in path that we do not have access like this :


/private/var/mobile/Library/Caches/com.apple.nsurlsessiond/Downloads/com.enterprise.bundleid/CFNetworkDownload_gQT2yY.tmp


Before it's signed by enterprise cetificate the path is accessable like this :


/private/var/mobile/Containers/Data/Application/***-***-***-***/Library/Caches/com.apple.nsurlsessiond/Downloads/com.app.bundleid/CFNetworkDownload_CMoX3A.tmp


com.app.bundleid listed above is the bundle-identifier of our app and com.enterprise.bundleid listed above is the application-identifier of the enterprise certificate

Same here.

Because it is pretty hard to debug enterprise-signed package, it took me two days to find this thread.

Thx for let me know that I am not the only one.

This sounds like a different issue from the one being discussed upthread (r. 32534132). Specifically, that issue:

  • Was with App Store apps

  • Cropped up intermittently

  • Could be cleared by restarting the device

It sounds like you’re in a very different sitation:

  • This is with an In-House (Enterprise) signed app

  • It is 100% reproducible

  • It isn’t cleared by a restart

Is that right?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for your reply.


Yes, you are right.


Though the situation are not the same as "(r. 32534132)", but the path it eventually downloaded into seems like the same.


Since all the features of my app are based on downloaded file, it's currently unusable now.


I create a bug report with ID 7314953 (https://feedbackassistant.apple.com/feedback/7314953)


Please take a look at it.

I’m not able to access your bug right now, but I just learnt about another bug along similar lines (r. 55614160). In that bug, the app has a mismatch between the bundle ID in their

Info.plist
and the bundle ID embedded within their App ID. Is that’s also the case with your app?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I'm not so sure if bug (r.55614160) would be the cause of mine.


I do try log my bundle ID in my first viewContronller and it does print what's been written in Info.plist .

I'm not so sure if bug (r.55614160) would be the cause of mine.

Yeah, now that I look at it again, 55614160 is the internal bug number associated with your bug, FB7314953.

I do try log my bundle ID in my first [view controller] and it does print what's been written in

Info.plist
.

That’s not what I’m getting at here. Rather, you need to look at your App ID. Consider this:

$ codesign -d --entitlements :- Test73426.app
…
<dict>
    <key>application-identifier</key>
    <string>SKMME9E2Y8.com.example.apple-samplecode.Test73426</string>
    …
</dict>
</plist>
$ plutil -convert xml1 -o /dev/stdout Test73426.app/Info.plist 
…
<dict>
    …
    <key>CFBundleIdentifier</key>
    <string>com.example.apple-samplecode.Test73426</string>
    …
</dict>
</plist>

The first shows the App ID, the second the bundle ID. The App ID is made up of the App ID prefix (typically your Team ID) and the bundle ID.

NSURLSession
is expecting this bundle ID to match the bundle ID from your
Info.plist
. Is that true for your enterprise build?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Yes, you're right.


Inside that enterprise build, bundle ID in App ID is not the same as the one defined in Info.plist.


But this build works fine on device that runing on system lower than iOS13 😟.

But this build works fine on device that runing on system lower than iOS 13.

Right. iOS 13 definitely changed to break this setup [1]. We are using your bug report (r. 55614160) to investigate how, and indeed if, we should react to that breakage.

My advice to you, however, is to avoid this problem entirely by ensuring that your bundle IDs line up. This misalignment puts you way off the beaten path. Even if we do decide to ‘fix’

NSURLSession
, it would not surprise me if you hit other weird problems caused by this, either now or in the future.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] This was part of a general effort to move away from an older, and less secure, way of identifying code.

Thanks for your reply.


Using the same bundle ID do solve the problem.


I've tried to use wildcard app ID like com.mycompany.* to sign app with bundle ID com.mycompany.haha to check if NSURLSession works.


But the result is this bug exists too.😟

NSURLSession downloads to inaccessible file
 
 
Q