AVAssetResourceLoaderDelegate and error handling

If we are using an AVAssetResourceLoaderDelegate, and performing our own playlist requests using a URLSession, what are some best practices for responding to the resource loading requests with errors? In other words, how best to populate the NSError domain, code, and userInfo values when calling finishLoadingWithError?

SImilarly, are there any things to look out for when the URLSession has caching enabled, and we receive HTTP 304s for live playlists? The URLSession appears to transparently handle the 304, and return a 200 with the cached data in the URLSession callbacks. But could there be edge cases where the URLSession’s cache is becoming invalid just as we get a 304?

Answered by Frameworks Engineer in 893331022

If the problem that's encountered is well-covered by an existing public error code in a public error domain, such as the NSURLErrorDomain, the best practice is to create an NSError with that code and domain. This will ensure the broadest possible recognition of the source of the problem.

If instead the problem is something peculiar to your implementation, and you have no expectation of end-user recovery or other mitigation, it's certainly possible to employ your own error domain and error code. In any such case, it may also be helpful to populate the NSError user dictionary key NSDebugDescriptionErrorKey.

Accepted Answer

If the problem that's encountered is well-covered by an existing public error code in a public error domain, such as the NSURLErrorDomain, the best practice is to create an NSError with that code and domain. This will ensure the broadest possible recognition of the source of the problem.

If instead the problem is something peculiar to your implementation, and you have no expectation of end-user recovery or other mitigation, it's certainly possible to employ your own error domain and error code. In any such case, it may also be helpful to populate the NSError user dictionary key NSDebugDescriptionErrorKey.

We were seeing some rare cases of sudden drift on live streams, where content would appear to be playing normally, and then we would suddenly see the audio and video be minutes apart from each other. This appeared to be related to HTTP 503 and 304 responses from the CDN on .m3u8 playlists.

This issue didn’t happen on a brand new project, using an AVPlayer without a resource loader delegate, so we suspected that our own handling of these responses in our own AVAssetResourceLoaderDelegate could be the cause.

We changed our code to the following, to handle the case of the 503s and other codes within the 400s-500s ranges. This did seem to solve the issue, but we weren't 100% certain if this was the right approach. Based on your answer, it sounds like we should just pass the HTTP code in directly instead of the "code: NSURLErrorBadServerResponse".

loadingRequest.finishLoading( with: NSError( domain: NSURLErrorDomain, code: NSURLErrorBadServerResponse, userInfo: [ NSURLErrorFailingURLErrorKey: url, NSURLErrorFailingURLStringErrorKey: url.absoluteString, "HTTPStatusCode": response.statusCode, ] ) )

NSURLSession and NSURLCache are designed to handle HTTP 304 responses safely, and you should not encounter race conditions in the scenario you described. The cache lookup and revalidation flow is handled in a way that ensures consistency throughout the lifecycle of a request, so a cached entry being invalidated concurrently while a 304 is being processed is not a concern.

That said, if you do run into any unexpected behavior in your specific use case, we'd encourage you to file a Feedback report with a reproducible example. That will help us investigate further and make sure things work correctly for your workflow.

AVAssetResourceLoaderDelegate and error handling
 
 
Q