{"record":{"id":"6d346f23051de210","repo":"ytdl-org/youtube-dl","slug":"error-desc","errorCode":null,"errorMessage":"error_desc","messagePattern":"error_desc","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/wat.py","lineNumber":67,"sourceCode":"\n    def _real_extract(self, url):\n        video_id = self._match_id(url)\n        video_id = video_id if video_id.isdigit() and len(video_id) > 6 else compat_str(int(video_id, 36))\n\n        # 'contentv4' is used in the website, but it also returns the related\n        # videos, we don't need them\n        # video_data = self._download_json(\n        #     'http://www.wat.tv/interface/contentv4s/' + video_id, video_id)\n        video_data = self._download_json(\n            'https://mediainfo.tf1.fr/mediainfocombo/' + video_id,\n            video_id, query={'context': 'MYTF1', 'pver': '4001000'})\n        video_info = video_data['media']\n\n        error_desc = video_info.get('error_desc')\n        if error_desc:\n            if video_info.get('error_code') == 'GEOBLOCKED':\n                self.raise_geo_restricted(error_desc, video_info.get('geoList'))\n            raise ExtractorError(error_desc, expected=True)\n\n        title = video_info['title']\n\n        formats = []\n\n        def extract_formats(manifest_urls):\n            for f, f_url in manifest_urls.items():\n                if not f_url:\n                    continue\n                if f in ('dash', 'mpd'):\n                    formats.extend(self._extract_mpd_formats(\n                        f_url.replace('://das-q1.tf1.fr/', '://das-q1-ssl.tf1.fr/'),\n                        video_id, mpd_id='dash', fatal=False))\n                elif f == 'hls':\n                    formats.extend(self._extract_m3u8_formats(\n                        f_url, video_id, 'mp4',\n                        'm3u8_native', m3u8_id='hls', fatal=False))\n","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/wat.py#L49-L85","documentation":"Raised by the Wat (wat.tv / TF1) extractor when the mediainfo.tf1.fr JSON contains a non-empty error_desc in video_info. If error_code is 'GEOBLOCKED' it first calls raise_geo_restricted with the allowed geoList; otherwise it raises with the service's own error text.","triggerScenarios":"Requesting https://mediainfo.tf1.fr/mediainfocombo/<video_id> with context=MYTF1 and pver=4001000 where the returned media object has error_desc set (geoblocking, removed video, unpublished content).","commonSituations":"Watching TF1/wat.tv content from outside France; videos delisted after broadcast rights expired; IDs from old URLs that no longer resolve in the MYTF1 catalog.","solutions":["Read error_desc — it is TF1's own message and states the exact reason.","For GEOBLOCKED, use a French IP or the geoList countries the response permits.","If the video was removed, find the content on another service.","Verify the video ID is current by opening the page on the MYTF1 site."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    info = ydl.extract_info(url)\nexcept GeoRestrictedError:\n    mark_geo_blocked(url, countries=['FR'])\nexcept ExtractorError as e:\n    log_skip(url, str(e))","preventionTips":["Route TF1/wat.tv requests through a French IP.","Catch GeoRestrictedError separately from ExtractorError — it carries the geoList metadata.","Validate video IDs against the MYTF1 site before bulk extraction."],"tags":["geo-restriction","api-error","extractor","wat","tf1"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}