ytdl-org/youtube-dl · error · ExtractorError
Episode %s is not available: %s
Error message
Episode %s is not available: %s
What it means
Catch-all sibling in BBCCoUkIE._extract_from_legacy_playlist: the noItems element carries a reason attribute the extractor does not recognize (anything other than preAvailability/postAvailability/noMedia), so it raises 'Episode %s is not available: %s' with the raw reason string. Expected=True; the raw reason is passed through verbatim for diagnosis.
Source
Thrown at youtube_dl/extractor/bbc.py:509
'http://www.bbc.co.uk/iplayer/playlist/%s' % playlist_id, playlist_id)
def _download_legacy_playlist_url(self, url, playlist_id=None):
return self._download_xml(
url, playlist_id, 'Downloading legacy playlist XML')
def _extract_from_legacy_playlist(self, playlist, playlist_id):
no_items = playlist.find('./{%s}noItems' % self._EMP_PLAYLIST_NS)
if no_items is not None:
reason = no_items.get('reason')
if reason == 'preAvailability':
msg = 'Episode %s is not yet available' % playlist_id
elif reason == 'postAvailability':
msg = 'Episode %s is no longer available' % playlist_id
elif reason == 'noMedia':
msg = 'Episode %s is not currently available' % playlist_id
else:
msg = 'Episode %s is not available: %s' % (playlist_id, reason)
raise ExtractorError(msg, expected=True)
for item in self._extract_items(playlist):
kind = item.get('kind')
if kind not in ('programme', 'radioProgramme'):
continue
title = playlist.find('./{%s}title' % self._EMP_PLAYLIST_NS).text
description_el = playlist.find('./{%s}summary' % self._EMP_PLAYLIST_NS)
description = description_el.text if description_el is not None else None
def get_programme_id(item):
def get_from_attributes(item):
for p in ('identifier', 'group'):
value = item.get(p)
if value and re.match(r'^[pb][\da-z]{7}$', value):
return value
get_from_attributes(item)
mediator = item.find('./{%s}mediator' % self._EMP_PLAYLIST_NS)
if mediator is not None:View on GitHub (pinned to 956b8c5855)
Solutions
- Read the interpolated reason string — it is the BBC's own code and usually self-explanatory (rights, takedown, etc.).
- Compare against the three known codes; if the new one is semantically equivalent to one of them (e.g. another geo code), add it to the if/elif chain in bbc.py:509 and submit upstream.
- Reproduce by fetching the legacy playlist XML for that id directly and inspecting noItems.
- Retry later — some transient backend states also surface as unknown reasons.
Example fix
// before
elif reason == 'noMedia':
msg = 'Episode %s is not currently available' % playlist_id
else:
msg = 'Episode %s is not available: %s' % (playlist_id, reason)
// after: map newly observed geo-style codes onto the geo message while keeping the raw code visible
else:
if 'geo' in (reason or '').lower():
msg = 'Episode %s is only available in the UK (reason: %s)' % (playlist_id, reason)
else:
msg = 'Episode %s is not available: %s' % (playlist_id, reason) Defensive patterns
Strategy: try-catch
Try / catch
try:
ydl.extract_info(episode_url)
except ExtractorError as e:
m = re.search(r'is not available: (\S+)', str(e))
if m:
classify_bbc_reason(m.group(1)) # log raw BBC reason; maybe a new geo/rights code
else:
raise Prevention
- Log the raw reason string; new BBC codes appearing here are an early signal of API change.
- Watch extractor updates after BBC backend releases introduce new noItems reasons.
- Classify unknown reasons as non-retryable until proven transient.
When it happens
Trigger: BBC adds a new noItems reason value (e.g. a new rights or takedown code) that the if/elif chain does not cover; the legacy EMP backend returns an unusual or malformed reason for a specific programme.
Common situations: Site-side API evolution introducing new reason codes after this extractor version was written; geo/rights-specific reason codes only served to some regions; debugging sessions where you need the raw reason string to classify a new failure mode.
Related errors
- Episode %s is not yet available
- Episode %s is no longer available
- Episode %s is not currently available
- %s returned error: %s
- error
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/0c15fb65dea4692e.
Report an issue: GitHub.