{"record":{"id":"3d4e034fcbd35b46","repo":"ytdl-org/youtube-dl","slug":"s-said-s-3d4e03","errorCode":null,"errorMessage":"%s said: %s","messagePattern":"%s said: %s","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/radiocanada.py","lineNumber":118,"sourceCode":"        if get_meta('protectionType'):\n            self.report_warning('This video is probably DRM protected.')\n\n        query = {\n            'connectionType': 'hd',\n            'deviceType': 'ipad',\n            'multibitrate': 'true',\n        }\n        if self._claims:\n            query['claims'] = self._claims\n        v_data = self._call_api('validation/v2/', video_id, app_code, query)\n        v_url = v_data.get('url')\n        if not v_url:\n            error = v_data['message']\n            if error == \"Le contenu sélectionné n'est pas disponible dans votre pays\":\n                raise self.raise_geo_restricted(error, self._GEO_COUNTRIES)\n            if error == 'Le contenu sélectionné est disponible seulement en premium':\n                self.raise_login_required(error)\n            raise ExtractorError(\n                '%s said: %s' % (self.IE_NAME, error), expected=True)\n        formats = self._extract_m3u8_formats(v_url, video_id, 'mp4')\n        self._sort_formats(formats)\n\n        subtitles = {}\n        closed_caption_url = get_meta('closedCaption') or get_meta('closedCaptionHTML5')\n        if closed_caption_url:\n            subtitles['fr'] = [{\n                'url': closed_caption_url,\n                'ext': determine_ext(closed_caption_url, 'vtt'),\n            }]\n\n        return {\n            'id': video_id,\n            'title': get_meta('Title') or get_meta('AV-nomEmission'),\n            'description': get_meta('Description') or get_meta('ShortDescription'),\n            'thumbnail': get_meta('imageHR') or get_meta('imageMR') or get_meta('imageBR'),\n            'duration': int_or_none(get_meta('length')),","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/radiocanada.py#L100-L136","documentation":"RadioCanadaBaseIE._extract_info calls validation/v2/ and, if the response contains no 'url', raises ExtractorError('%s said: %s' % (IE_NAME, error), expected=True) using v_data['message'] — after first checking for two known French messages (geo-restriction -> raise_geo_restricted, premium-only -> raise_login_required). So this branch is the generic validation failure: the API explicitly refused to provide a stream URL for a reason other than geo or premium.","triggerScenarios":"validation/v2/ returns a dict without 'url' and with a message that is neither 'Le contenu sélectionné n'est pas disponible dans votre pays' nor '... seulement en premium' — e.g. expired content, removed media, or new refusal messages; note KeyError-style failure is avoided only because message is read via v_data['message'], which must exist.","commonSituations":"Expired news clips or live streams past their availability window; messages reworded by Radio-Canada so the geo/premium string matches fail and fall through to the generic error; deleted episodes on Tou.tv.","solutions":["Read the French message in the error text — it states the actual refusal reason from the API.","Confirm the content is still available on the Radio-Canada/Tou.tv site in a browser.","Update youtube-dl so newly worded geo/premium messages are recognized and routed to the proper handling.","If it is availability-window related, there is no client fix — the content is gone server-side."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    info = ydl.extract_info(url)\nexcept ExtractorError as e:\n    if 'said:' in str(e):\n        read_french_message(e)  # names the real refusal reason","preventionTips":["Check content availability on the Radio-Canada site before queueing old clips.","Update youtube-dl so geo/premium messages route to their dedicated handlers instead of the generic branch.","Log the API message verbatim — it is the authoritative refusal reason."],"tags":["radiocanada","validation-api","content-unavailable","expected-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}