{"record":{"id":"1aad5d69044ade49","repo":"ytdl-org/youtube-dl","slug":"s-returned-error-s","errorCode":null,"errorMessage":"%s returned error: %s","messagePattern":"(.+?) returned error: (.+?)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/bbc.py","lineNumber":341,"sourceCode":"        for connection in self._extract_connections(media):\n            cc_url = url_or_none(connection.get('href'))\n            if not cc_url:\n                continue\n            captions = self._download_xml(\n                cc_url, programme_id, 'Downloading captions', fatal=False)\n            if not isinstance(captions, compat_etree_Element):\n                continue\n            subtitles['en'] = [\n                {\n                    'url': connection.get('href'),\n                    'ext': 'ttml',\n                },\n            ]\n            break\n        return subtitles\n\n    def _raise_extractor_error(self, media_selection_error):\n        raise ExtractorError(\n            '%s returned error: %s' % (self.IE_NAME, media_selection_error.id),\n            expected=True)\n\n    def _download_media_selector(self, programme_id):\n        last_exception = None\n        for media_set in self._MEDIA_SETS:\n            try:\n                return self._download_media_selector_url(\n                    self._MEDIA_SELECTOR_URL_TEMPL % (media_set, programme_id), programme_id)\n            except BBCCoUkIE.MediaSelectionError as e:\n                if e.id in ('notukerror', 'geolocation', 'selectionunavailable'):\n                    last_exception = e\n                    continue\n                self._raise_extractor_error(e)\n        self._raise_extractor_error(last_exception)\n\n    def _download_media_selector_url(self, url, programme_id=None):\n        media_selection = self._download_json(","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/bbc.py#L323-L359","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["For 'geolocation'/'notukerror': use a UK IP (UK VPN/relay) or accept that the programme is geo-restricted.","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.","Retry later if the programme was just published and the selector backend has not caught up.","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."],"exampleFix":"// before\nlast_exception = None\nfor media_set in self._MEDIA_SETS:\n    try:\n        return self._download_media_selector_url(self._MEDIA_SELECTOR_URL_TEMPL % (media_set, programme_id), programme_id)\n    except BBCCoUkIE.MediaSelectionError as e:\n        if e.id in ('notukerror', 'geolocation', 'selectionunavailable'):\n            last_exception = e\n\n// after: annotate the geo case with actionable wording for end users\nif last_exception is not None:\n    if last_exception.id in ('notukerror', 'geolocation'):\n        raise ExtractorError('BBC iPlayer programmes are only available in the UK (error: %s)' % last_exception.id, expected=True)\n    raise ExtractorError('%s returned error: %s' % (self.IE_NAME, last_exception.id), expected=True)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    ydl.extract_info('https://www.bbc.co.uk/iplayer/episode/%s' % pid)\nexcept ExtractorError as e:\n    if 'returned error: geolocation' in str(e) or 'returned error: notukerror' in str(e):\n        raise RegionBlocked('BBC programme %s requires a UK IP' % pid) from e\n    if 'returned error: selectionunavailable' in str(e):\n        raise NotFound('no media set for %s; check the episode id' % pid) from e\n    raise","preventionTips":["For UK-only content, route requests through a UK IP from the start.","Check the programme still has a 'Watch' button on its page before extracting.","Map the three known error ids to user-facing causes instead of surfacing raw extractor text."],"tags":["bbc","geo-restriction","media-selector","availability","extractor"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}