"SKDownload encountered a sandboxing error" under iOS 14 only

Hi there,

We're tracking an issue both in the sandbox environment and in production whereby download of App Store hosted in-app purchase content is not working properly. This is something that only happens on iOS 14 - all beta versions up to and including beta 3 - and has occurred with no change in our in-app purchase code. Either there is a bug in iOS 14 StoreKit, or something changed which breaks our implementation.

In production our logs show that in-app purchase SKPaymentTransaction object flow occurs nominally, with purchased and restored transactions presented and handled as expected.

Ultimately we provide content by calling

Code Block
[[SKPaymentQueue defaultQueue] startDownloads:transaction.downloads]

with a non-nil transaction whose first downloads array object is non-nil and in the 'Waiting' SKDownload state. Ultimately a 'Finished' download object is returned via updatedDownloads:, but on processing the (supposedly) completed download NSFileManager fails to move the content files into the app directory.

Investigating in the Sandbox allows us to see more via the debugger.

It appears that the updatedDownloads: StoreKit method does not return 'Active' SKDownload objects at any time. We are starting a 'Waiting' SKDownload object and then seeing nothing until one of two cryptic iOS error message appears in the debugger:

SKDownload encountered a sandboxing error: 0

or

SKDownload encountered a sandboxing error: 35

The SKDownload is then returned to the updatedDownloads: method in the 'Finished' state, and not the 'Failed' state as one might have expected. When attempting to process the finished download we have verified via NSFileManager that the source files we expect DO exist at the source location (the temporary content download directory) and DO NOT exist at the destination location prior to attempting to move the files across. It would appear that the download is actually executing, but we are not being informed of its progress, and cannot move the resultant files into our app directory.

NSFileManager gives the following error on attempting a file move:


Error Domain=NSCocoaErrorDomain Code=513 "“redactedFilename.jpg” couldn’t be moved because you don’t have permission to access “redactedFolderName”." UserInfo={NSSourceFilePathErrorKey=/private/var/mobile/Library/OnDemandResources/AssetPacks/StoreKit/6050167547064785133/Contents/Content/25/redactedFilename.jpg, NSUserStringVariant=(
  Move
), NSDestinationFilePath=/var/mobile/Containers/Data/Application/63151311-068D-4421-89BB-0E7AAEF65C62/Library/Application Support/Packs/redactedFolderName/redactedFilename.jpg, NSFilePath=/private/var/mobile/Library/OnDemandResources/AssetPacks/StoreKit/6050167547064785133/Contents/Content/25/redactedFilename.jpg, NSUnderlyingError=0x281aae2b0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

We have double checked, and the target folder has been created and exists:

/var/mobile/Containers/Data/Application/63151311-068D-4421-89BB-0E7AAEF65C62/Library/Application Support/Packs/redactedFolderName

Can anyone shed any light on what is occurring here? Why do I not have permission to move files into the application support directory of my own app, into a folder which I created successfully moments prior? I've not found any hint of other people experiencing similar issues so far. If it is a simple case of needing to attain more permissions, that doesn't explain why I am not seeing 'Active' SKDownloads returned via StoreKit's updatedDownloads: method.

I would really appreciate any insight from anyone - thank you in advance.

Kind regards,

Alex
I've made some progress (still on iPadOS 14 beta 8) as I believe I've managed to fix the crashes I was experiencing during content download. My downloads now make it to the end and usually succeed, but sometimes they fail with the same behavior reported by hithlimited.

My crashes were fixed by removing my call to [[SKPaymentQueue defaultQueue] startDownloads:] in response to SKDownloadStateWaiting. It took quite a long time after making this change for all downloads to stop. I suspect there were many items in the queue, including those from previous run sessions. My guess is that it was spamming the payment queue because it's called so frequently in iOS 14. Note that I had no problems on iOS 10-13 with this code in place.

When a download fails, I'm seeing this in [RMStoreObserver storeDownloadFailed:]:

Code Block
storeDownloadFailed:
- ProductID = co.uk.redacted
- Transaction = <SKPaymentTransaction: 0x282b99a90>
- Download = <SKDownload: 0x282b99ad0>
- Description = “mzafbenc.5781985184949448504” couldn’t be moved to “StoreKit” because an item with the same name already exists.
- FailureReason = A file with the name “mzafbenc.5781985184949448504” already exists.


So the good news is that we can both independently reproduce at least one issue, which is something. The bad news is that (to my knowledge) this is a problem with StoreKit and outside our control.

Wait for beta 9?

Unfortunately I'm still seeing issues in iOS 14.0 GM seed. I'm using a fresh install to avoid issues from prior beta installations. Can anyone else confirm this?

I'm still seeing paymentQueue:updatedDownloads: called with finished downloads with nil/zero-length download.contentURL or with no content at the URL. Sometimes this method gets called twice, the first time there is no content and the second time there is content.

I have heard nothing direct from Apple, but I note that the status of my feedback report has changed. 'Recent similar reports' is marked as 'less than 10', and resolution has changed to 'potential fix identified - in iOS 14'. I am confused as to how there can be so few similar reports given that everyone has to use the same API in the same way.
And now it seems like there are additional StoreKit / App Store server issues making further testing difficult:


SKPaymentQueue: 0x2826811c0>: Payment completed with error: Error Domain=ASDErrorDomain Code=500 "Unhandled exception" UserInfo={NSUnderlyingError=0x282b94180 {Error Domain=AMSErrorDomain Code=301 "Invalid Status Code" UserInfo={NSLocalizedDescription=Invalid Status Code, NSLocalizedFailureReason=The response has an invalid status code}}, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception


These issues persist in 14.2 beta.

I'm still seeing paymentQueue:updatedDownloads: called with finished downloads with nil/zero-length download.contentURL or with no content at the URL. Sometimes this method gets called twice, the first time there is no content and the second time there is content.

I'm still on iOS 14.0 GM. I've seen this issue occur once, but have since performed 20-30 downloads which all completed successfully. This failure pattern made me wonder if there was something 'left over' in the payment queue from a previous beta or run session, but that's pure speculation.

I'm also a bit baffled as to why there aren't more reports about this. My app utilizes IAP content lightly, but there must be developers whose business model heavily depends upon it - surely they must be suffering?

Do your failed downloads eventually succeed if you retry multiple times? I'm thinking about this from a customer support perspective. If a failed download will eventually succeed then at least I can suggest that a customer should keep retrying.

I'm also a bit baffled as to why there aren't more reports about this. My app utilizes IAP content lightly, but there must be developers whose business model heavily depends upon it - surely they must be suffering?

/nods head

Do your failed downloads eventually succeed if you retry multiple times? I'm thinking about this from a customer support perspective. If a failed download will eventually succeed then at least I can suggest that a customer should keep retrying.

The problems do seem intermittent - retrying (potentially multiple times) can result in success. We do recommend people reinstall (to force the caches/ directory to be purged) - thinking about adding a function to purge the caches directory if no downloads are in progress!

A question: do you see tremendous lag in the finishing and removal of transactions from the payment queue? Pre iOS 14 we would batch finish transactions and see the paymentQueue:removedTransactions: method called very rapidly. Now it is painfully slow and can take up to a minute to finish say 30 transactions (we have a lot of in-app purchases).
Has this issue been solved? I'm currently facing the exact same problem with files no longer being downloaded to the Cache folder from Apple Hosted Content.

With the mentioned solution about just copying from /private/var/mobile/Library/OnDemandResources/AssetPacks/StoreKit/ instead, is there any way to access this folder? Similarly to the way that we accessed the Contents from the download:

Code Block
download.contentURL?.appendingPathComponent("Contents")


Thanks!
We are experiencing the same problem. Did anyone find a fix for the error: “couldn’t be moved because you don’t have permission to access”

Thanks!
"SKDownload encountered a sandboxing error" under iOS 14 only
 
 
Q