{"record":{"id":"daf6d2068efd425d","repo":"ytdl-org/youtube-dl","slug":"unable-to-find-song-or-singer-names","errorCode":null,"errorMessage":"Unable to find song or singer names","messagePattern":"Unable to find song or singer names","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/kuwo.py","lineNumber":333,"sourceCode":"    _FORMATS = KuwoBaseIE._FORMATS + [\n        {'format': 'mkv', 'ext': 'mkv', 'preference': 250},\n        {'format': 'mp4', 'ext': 'mp4', 'preference': 200},\n    ]\n\n    def _real_extract(self, url):\n        song_id = self._match_id(url)\n        webpage = self._download_webpage(\n            url, song_id, note='Download mv detail info: %s' % song_id,\n            errnote='Unable to get mv detail info: %s' % song_id)\n\n        mobj = re.search(\n            r'<h1[^>]+title=\"(?P<song>[^\"]+)\">[^<]+<span[^>]+title=\"(?P<singer>[^\"]+)\"',\n            webpage)\n        if mobj:\n            song_name = mobj.group('song')\n            singer_name = mobj.group('singer')\n        else:\n            raise ExtractorError('Unable to find song or singer names')\n\n        formats = self._get_formats(song_id, tolerate_ip_deny=True)\n\n        mv_url = self._download_webpage(\n            'http://www.kuwo.cn/yy/st/mvurl?rid=MUSIC_%s' % song_id,\n            song_id, note='Download %s MV URL' % song_id)\n        formats.append({\n            'url': mv_url,\n            'format_id': 'mv',\n        })\n\n        self._sort_formats(formats)\n\n        return {\n            'id': song_id,\n            'title': song_name,\n            'creator': singer_name,\n            'formats': formats,","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/kuwo.py#L315-L351","documentation":"Raised by the Kuwo MV extractor when the MV detail page does not match the <h1 title=...><span title=...> pattern used to read the song and singer names. Unlike most errors here it is not expected=True, so youtube-dl treats it as an extractor failure (page layout changed) rather than a user error.","triggerScenarios":"Downloading a kuwo.cn MV page (e.g. /mv/<id>) whose markup no longer contains an h1 element with a title attribute immediately followed by a span with a title attribute, so re.search returns None and the else branch raises.","commonSituations":"Kuwo shipping a redesigned MV page (class/attribute changes); MVs served by a newer SPA shell without server-rendered h1; regional A/B page variants; an old youtube-dl version whose regex predates a past layout change.","solutions":["Update youtube-dl (or migrate to yt-dlp) so you have the current MV-page regex","Open the MV URL in a browser, inspect the h1/heading markup, and verify the page actually renders song/singer data server-side","If the page is now JS-rendered, extract the data from the underlying API the page calls and report the breakage upstream","File an extractor issue with the failing URL so the regex gets updated"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import re\n\ndef kuwo_mv_names_present(page_html):\n    return re.search(r'<h1[^>]+title=\"[^\"]+\">[^<]+<span[^>]+title=\"[^\"]+\"', page_html) is not None","typeGuard":null,"tryCatchPattern":"try:\n    ydl.extract_info(url)\nexcept ExtractorError as e:\n    if 'song or singer names' in str(e):\n        logger.warning('kuwo MV layout changed for %s', url)  # report upstream\n    else:\n        raise","preventionTips":["Pin a recent extractor version and update promptly when sites redesign","Monitor extraction jobs for non-expected ExtractorErrors as layout-change signals"],"tags":["kuwo","mv","regex-breakage","extractor"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}