Edited at

How to handle error which was detected by AVPlayer that get video content from HLS

More than 1 year has passed since last update.

Hi there. How are you doing?

I'm hiroakit that is iOS/tvOS Engineer.

This letter introduces you to the basic error handling of AVPlayer.


AVPlayer will provide a video experience to your end-user.

And it may get some error from server interaction.

So it give us to issues below:

  • What kind of errors do AVPlayer catch?

  • What should app do to handle error which was catched by AVPlayer?

Then I looked up these issues on Apple's documents.

What kind of errors do AVPlayer catch?

AVPlayer will get these errors:

  • AVFoundationErrorDomain

  • CoreMediaErrorDomain


AVPlayer will get AVFoundationErrorDomain errors when failures occur.

via: https://developer.apple.com/videos/play/wwdc2017/514/?time=875


Network errors
HTTP 4xx errors, HTTP 5xx errors, TCP/IP, DNS errors
AVErrorContentIsUnavailable, AVErrorNoLongerPlayable

Master playlist, media playlist, media file, keys timeout
AVErrorContentIsUnavailable, AVErrorNoLongerPlayable

Format errors
Playlist format error, Key format error, Session data format error

Live playlist update errors
Must update live playlist in time as per HLS Spec

The above AVFoundationErrorDomain error has assigned error code by Apple.

It is below:






Example is here.

Error Domain=AVFoundationErrorDomain Code=-11867 "See -[AVPlayerItem errorLog] for 2 events" UserInfo={NSLocalizedDescription=Playback Stopped, NSUnderlyingError=0x60c000444b90 {Error Domain=CoreMediaErrorDomain Code=-12880 "Can not proceed after removing variants" UserInfo={NSDescription=Can not proceed after removing variants}}, NSDebugDescription=See -[AVPlayerItem errorLog] for 2 events, NSLocalizedFailureReason=Could not download required resources.})

AVPlayer will get to detect these errors at the start of playback.

If you handle AVFoundationErrorDomain errors, Your app should observe AVPlayer.status and AVPlayer.currentItem.status


Your app receive errors from AVPlayerItemNewErrorLogEntry notification.

The notification has CoreMediaErrorDomain error.

Example is here.

Error Domain=CoreMediaErrorDomain Code=-12642 "Playlist parse error" (See -[AVPlayerItem errorLog] for 2 events) UserInfo={NSDescription=Playlist parse error, NSDebugDescription=See -[AVPlayerItem errorLog] for 2 events})

AVPlayer will catch CoreMediaErrorDomain errors while playback video.

Expected Failures and Error Codes

AVPlayer expect these error code when a failure occurs on HTTP.

via: https://developer.apple.com/videos/play/wwdc2017/514/?time=218

Error Code

Authentication failures
401 Unauthorized

Client doesn’t have permissions
403 Forbidden

Resource unavailable but may become available in the future
404 Not Found

Resource unavailable and will never become available in the future
410 Gone

Internal server errors
500 Internal Server Error

Invalid response from gateway
502 Bad Gateway

Server unavailable
503 Service Unavailable

Gateway timeouts
504 Gateway Time-Out

When AVPlayer get these error codes, it exec the recovery below:

  • 401, 403, 404: Retry

  • 410, 500, 502, 503, 504: Switch other variants.

iOS 11 catch temporary resource/server unavailability with EXT-X-GAP tag in Playlist.

It is unverified I wish to Write this feature on next letter.

What should app do to handle error which was catched by AVPlayer?

Get error via these methods below:

  • Watch AVPlayer.status and AVPlayerItem.status

  • Listen to these notifications

    • NSNotification.Name.AVPlayerItemFailedToPlayToEndTime

    • NSNotification.Name.AVPlayerItemNewErrorLogEntry

Example is here.

func foo() {

// Get AVPlayerItem
let url: URL // something url
let asset = AVURLAsset(URL: url)
let item = AVPlayerItem(asset: asset)

// Get AVPlayer
self.player = AVPlayer(playerItem: item)

// Add observer for AVPlayer status and AVPlayerItem status
self.player.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.new, .initial], context: nil)
self.player.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options:[.new, .initial], context: nil)

// Watch notifications
let center = NotificationCenter.default
center.addObserver(self, selector:"newErrorLogEntry:", name: .AVPlayerItemNewErrorLogEntry, object: player.currentItem)
center.addObserver(self, selector:"failedToPlayToEndTime:", name: .AVPlayerItemFailedToPlayToEndTime, object: player.currentItem)

// Observe If AVPlayerItem.status Changed to Fail
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if let player: AVPlayer = object as? AVPlayer && keyPath == #keyPath(AVPlayer.currentItem.status) {
let newStatus: AVPlayerItemStatus
if let newStatusAsNumber = change?[NSKeyValueChangeKey.newKey] as? NSNumber {
newStatus = AVPlayerItemStatus(rawValue: newStatusAsNumber.intValue)!
} else {
newStatus = .unknown
if newStatus == .failed {
NSLog("Error: \(String(describing: self.player?.currentItem?.error?.localizedDescription)), error: \(String(describing: self.player?.currentItem?.error))")

// Getting error from Notification payload
func newErrorLogEntry(_ notification: Notification) {
guard let object = notification.object, let playerItem = object as? AVPlayerItem else {
guard let errorLog: AVPlayerItemErrorLog = playerItem.errorLog() else {
NSLog("Error: \(errorLog)")

func failedToPlayToEndTime(_ notification: Notification) {
let error = notification.userInfo![AVPlayerItemFailedToPlayToEndTimeErrorKey]
NSLog("Error: \(error?.localizedDescription), error: \(error)")


In this letter, I described how to handle errors by the approach below:

  • Watch AVPlayer.status and AVPlayerItem.status

  • Listen to these notifications

    • NSNotification.Name.AVPlayerItemFailedToPlayToEndTime

    • NSNotification.Name.AVPlayerItemNewErrorLogEntry

Perhaps we can get how to reduce errors or more good error handling by taking part in the discussion from the server side (e.g, EXT-X-GAP, Fail. So error handling is debatable. It will take good for client side too.

Finally, I think that i/we can still improve the video user experience, so any ideas are welcome. Then we can do better together.