I have been battling this intermittent error for some time. It is generally random and has been difficult to reproduce until yesterday when I stumbled across a way to reproduce it each time. I can cause the code to throw this error:
Task <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2103, _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundDownloadTask <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"BackgroundDownloadTask <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1>",
"LocalDownloadTask <70E3909F-8C30-4F34-A8B0-4AF3B41DD81B>.<1>"
), NSLocalizedDescription=The request timed out., _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://redacted*, NSErrorFailingURLKey=https://redacted*}
*"redacted" is the backend URL, and it is the correct and same path for each
immediately after restarting an actual device. I have been over the following threads with no results:
What is kCFStreamErrorCodeKey=-4 (kCFStreamErrorDomainKey=4)
Request timed out with _kCFStreamErrorCodeKey=60
How to better diagnose -1001 "The request timed out." URLSession errors
Random timed out error on app start
Because I was able to reproduce it, I have been able to get the following logs:
Last bit of information is that I had Network Instruments running, and when this error occurred, I found that the Connection ID was "No Connection" and it appears the request was never actually sent, though it waited the full time out for a backend response.
Any help would be appreciated. This data request is being used after sending a certain APNs to update necessary data in the background, and has been the source of many user complaints.
So, I think the issue here is with your timeoutIntervalForResource. More specifically, breaking down the two timeouts:
-
"timeoutIntervalForRequest"-> The is the network level timeout. When a connection is attempted, the system tries for 15s and then "gives up" if it doesn't complete it gives up. In you particular case, 15s is "short", but not unreasonable.
-
"timeoutIntervalForResource"-> This is the "overall" timeout on the entire request, meaning how long should the system keep the request "around" before discarding the entire request. In concrete terms, "if you can't get me this data in the next <insert time> don't bother trying at all". In that context, 15s is WAY to short, as you're basically saying "if you can't get it now, don't bother at all". Note that the default here is 7 days, which is the kind of time window you should be thinking in terms of.
Covering a few edge cases:
Using the same server endpoint, I am successfully completing the fetch when the app starts up, albeit using data(for:delegate:).
-
The "data(for:delegate:)" delegate changes things, as I believe it will end up doing the transfer in process (not as a true background transfer).
-
Having your app in the foreground also skews results, as it means your "background" transfer is getting much higher priority than it normally would.
The issue does not just occur after restart. It will also randomly occur, but I can replicate it reliably after restart.
If you're launching immediately after restart, then you can easily be in a situation where our radios have not fully initialized and/or the backend support daemon hasn't fully launched. Those delays could easily add 5-15s of delay in starting your transfer, at which point we'll end the entire request based on timeoutIntervalForResource.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware