ytdl-org/youtube-dl · error · ExtractorError

%s returned error: %s

Error message

%s returned error: %s

What it means

Raised via BBCCoUkIE._raise_extractor_error after _download_media_selector has tried every media set in _MEDIA_SETS and each one raised a MediaSelectionError whose id was one of 'notukerror', 'geolocation', or 'selectionunavailable'. The message interpolates the extractor name (BBC iPlayer) and the last error id, e.g. 'BBC iPlayer returned error: geolocation'. It is expected=True, signalling a server-side availability restriction rather than a code defect.

Source

Thrown at youtube_dl/extractor/bbc.py:341

        for connection in self._extract_connections(media):
            cc_url = url_or_none(connection.get('href'))
            if not cc_url:
                continue
            captions = self._download_xml(
                cc_url, programme_id, 'Downloading captions', fatal=False)
            if not isinstance(captions, compat_etree_Element):
                continue
            subtitles['en'] = [
                {
                    'url': connection.get('href'),
                    'ext': 'ttml',
                },
            ]
            break
        return subtitles

    def _raise_extractor_error(self, media_selection_error):
        raise ExtractorError(
            '%s returned error: %s' % (self.IE_NAME, media_selection_error.id),
            expected=True)

    def _download_media_selector(self, programme_id):
        last_exception = None
        for media_set in self._MEDIA_SETS:
            try:
                return self._download_media_selector_url(
                    self._MEDIA_SELECTOR_URL_TEMPL % (media_set, programme_id), programme_id)
            except BBCCoUkIE.MediaSelectionError as e:
                if e.id in ('notukerror', 'geolocation', 'selectionunavailable'):
                    last_exception = e
                    continue
                self._raise_extractor_error(e)
        self._raise_extractor_error(last_exception)

    def _download_media_selector_url(self, url, programme_id=None):
        media_selection = self._download_json(

View on GitHub (pinned to 956b8c5855)

Solutions

  1. For 'geolocation'/'notukerror': use a UK IP (UK VPN/relay) or accept that the programme is geo-restricted.
  2. For 'selectionunavailable': double-check the programme id from the URL; the episode may have been pulled — try the programme's episode list page for a current id.
  3. Retry later if the programme was just published and the selector backend has not caught up.
  4. If you control the caller, treat this error as expected (it is raised expected=True) and surface 'not available in your region' to end users instead of a stack trace.

Example fix

// before
last_exception = None
for media_set in self._MEDIA_SETS:
    try:
        return self._download_media_selector_url(self._MEDIA_SELECTOR_URL_TEMPL % (media_set, programme_id), programme_id)
    except BBCCoUkIE.MediaSelectionError as e:
        if e.id in ('notukerror', 'geolocation', 'selectionunavailable'):
            last_exception = e

// after: annotate the geo case with actionable wording for end users
if last_exception is not None:
    if last_exception.id in ('notukerror', 'geolocation'):
        raise ExtractorError('BBC iPlayer programmes are only available in the UK (error: %s)' % last_exception.id, expected=True)
    raise ExtractorError('%s returned error: %s' % (self.IE_NAME, last_exception.id), expected=True)
Defensive patterns

Strategy: try-catch

Try / catch

try:
    ydl.extract_info('https://www.bbc.co.uk/iplayer/episode/%s' % pid)
except ExtractorError as e:
    if 'returned error: geolocation' in str(e) or 'returned error: notukerror' in str(e):
        raise RegionBlocked('BBC programme %s requires a UK IP' % pid) from e
    if 'returned error: selectionunavailable' in str(e):
        raise NotFound('no media set for %s; check the episode id' % pid) from e
    raise

Prevention

When it happens

Trigger: Requesting media selector JSON for a programme whose id returns an error object: 'geolocation' when the request IP is outside the UK, 'notukerror' when the programme is UK-only and the caller is abroad, 'selectionunavailable' when no media set exists for that programme id. The loop in _download_media_selector only re-raises after all media sets fail with a retryable/terminal id in that tuple.

Common situations: Running the extractor from a non-UK IP against UK-only content (the dominant case); supplying a programme id that exists in one brand but not the media-selector backend; VPN exit nodes detected by the BBC; programme unpublished after the page went live.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/1aad5d69044ade49. Report an issue: GitHub.