{"record":{"id":"896241a92e992f0d","repo":"ytdl-org/youtube-dl","slug":"youtube-said-s","errorCode":null,"errorMessage":"YouTube said: %s","messagePattern":"YouTube said: (.+?)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/youtube.py","lineNumber":4038,"sourceCode":"                    continue\n                message = self._get_text(alert_dict, 'text')\n                if message:\n                    yield alert_type, message\n\n        errors, warnings = [], []\n        _IGNORED_WARNINGS = T('Unavailable videos will be hidden during playback')\n        for alert_type, alert_message in alerts():\n            if alert_type.lower() == 'error' and fatal:\n                errors.append([alert_type, alert_message])\n            elif alert_message not in _IGNORED_WARNINGS:\n                warnings.append([alert_type, alert_message])\n\n        for alert_type, alert_message in itertools.chain(warnings, errors[:-1]):\n            self.report_warning(\n                'YouTube said: %s - %s' % (alert_type, alert_message),\n                only_once=only_once)\n        if errors:\n            raise ExtractorError(\n                'YouTube said: %s' % (errors[-1][1],), expected=expected)\n\n    def _extract_from_tabs(self, item_id, webpage, data, tabs):\n        selected_tab = self._extract_selected_tab(tabs)\n        renderer = traverse_obj(data, ('metadata', 'channelMetadataRenderer'),\n                                expected_type=dict) or {}\n        playlist_id = item_id\n        title = description = None\n        if renderer:\n            channel_title = txt_or_none(renderer.get('title')) or item_id\n            tab_title = txt_or_none(selected_tab.get('title'))\n            title = join_nonempty(\n                channel_title or item_id, tab_title,\n                txt_or_none(selected_tab.get('expandedText')),\n                delim=' - ')\n            description = txt_or_none(renderer.get('description'))\n            playlist_id = txt_or_none(renderer.get('externalId')) or playlist_id\n        else:","sourceCodeStart":4020,"sourceCodeEnd":4056,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/youtube.py#L4020-L4056","documentation":"Raised by _extract_and_report_alerts when the YouTube response's alerts array contains an alert of type 'error' (and fatal=True): the last error alert's message becomes 'YouTube said: <message>'. Non-error alerts and 'Unavailable videos will be hidden during playback' are only warned. expected comes from the caller, so playlist-level extraction usually treats it as an expected, user-visible condition.","triggerScenarios":"Any channel/playlist/mix extraction whose API response includes an error alert — e.g. 'This video is unavailable', 'The playlist does not exist', 'This video is private' inside playlist continuation payloads.","commonSituations":"Dead/private playlist or channel URLs; playlists where YouTube injects error alerts for removed entries; mix/radio playlists that expire; region-dependent availability alerts.","solutions":["Act on the alert message text — it is YouTube's own statement about the playlist/channel item (removed, private, nonexistent).","Verify the URL opens in a browser; nonexistent or private playlists legitimately error.","Update youtube-dl if alert handling or the surrounding tab extraction regressed.","For batch crawling, catch this per-playlist and continue with other items."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"def has_error_alerts(data: dict) -> bool:\n    return any(a.get('alertRenderer', {}).get('type', '').lower() == 'error'\n               for a in (data.get('alerts') or []))","typeGuard":null,"tryCatchPattern":"try:\n    entries = ydl.extract_info(playlist_url)\nexcept ExtractorError as e:\n    if str(e).startswith('YouTube said:'):\n        skip_playlist(playlist_url)  # upstream error alert; read message text\n    else:\n        raise","preventionTips":["Check that playlist/channel URLs resolve in a browser before batch jobs.","Log the alert message verbatim — it identifies private/deleted/nonexistent items deterministically."],"tags":["youtube","alerts","playlist","expected-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}