{"record":{"id":"2eec7c6ba45f3c3e","repo":"yt-dlp/yt-dlp","slug":"unable-to-download-video-subtitles-for-sub-lang-r","errorCode":null,"errorMessage":"Unable to download video subtitles for {sub_lang!r}: {err}","messagePattern":"Unable to download video subtitles for (.+?): (.+?)","errorType":"exception","errorClass":"DownloadError","httpStatus":null,"severity":"error","filePath":"yt_dlp/YoutubeDL.py","lineNumber":4501,"sourceCode":"                    sub_info['filepath'] = sub_filename\n                    ret.append((sub_filename, sub_filename_final))\n                    continue\n                except OSError:\n                    self.report_error(f'Cannot write video subtitles file {sub_filename}')\n                    return None\n\n            try:\n                sub_copy = sub_info.copy()\n                sub_copy.setdefault('http_headers', info_dict.get('http_headers'))\n                self.dl(sub_filename, sub_copy, subtitle=True)\n                sub_info['filepath'] = sub_filename\n                ret.append((sub_filename, sub_filename_final))\n            except (DownloadError, ExtractorError, OSError, ValueError, *network_exceptions) as err:\n                msg = f'Unable to download video subtitles for {sub_lang!r}: {err}'\n                if self.params.get('ignoreerrors') is not True:  # False or 'only_download'\n                    if not self.params.get('ignoreerrors'):\n                        self.report_error(msg)\n                    raise DownloadError(msg)\n                self.report_warning(msg)\n        return ret\n\n    def _write_thumbnails(self, label, info_dict, filename, thumb_filename_base=None):\n        \"\"\" Write thumbnails to file and return list of (thumb_filename, final_thumb_filename); or None if error \"\"\"\n        write_all = self.params.get('write_all_thumbnails', False)\n        thumbnails, ret = [], []\n        if write_all or self.params.get('writethumbnail', False):\n            thumbnails = info_dict.get('thumbnails') or []\n            if not thumbnails:\n                self.to_screen(f'[info] There are no {label} thumbnails to download')\n                return ret\n        multiple = write_all and len(thumbnails) > 1\n\n        if thumb_filename_base is None:\n            thumb_filename_base = filename\n        if thumbnails and not thumb_filename_base:\n            self.write_debug(f'Skipping writing {label} thumbnail')","sourceCodeStart":4483,"sourceCodeEnd":4519,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/YoutubeDL.py#L4483-L4519","documentation":"Raised by YoutubeDL._download_subtitle when the actual subtitle file download (self.dl on the subtitle URL) fails with DownloadError, ExtractorError, OSError, ValueError, or any network exception. The message embeds the language code (e.g. 'en') and the underlying error text. Behavior depends on 'ignoreerrors': when False, report_error() prints it and a DownloadError is raised (aborting the video); when 'only_download', DownloadError is raised for the caller to catch; when True, it degrades to a warning and processing continues.","triggerScenarios":"Running ydl.download()/ydl.extract_info() with writesubtitles/writeautomaticsub and subtitleslangs set, where the subtitle URL returns 404/403, the extractor published a stale subtitle URL, a connection error occurs, or the sub_info dict is malformed (ValueError). Also hit when a subtitle format requires headers/cookies not forwarded from info_dict['http_headers'].","commonSituations":"Batch downloads with --write-subs where one video's subtitle track is missing or geo-blocked; YouTube auto-caption URLs expiring before download; subtitles listed by the extractor but later removed; corporate proxies causing network_exceptions.","solutions":["Read the wrapped {err} text — it names the real cause (HTTP 404, timeout, etc.) and that is what must be fixed.","If missing subs are acceptable, set 'ignoreerrors': True (CLI: --ignore-errors) so the failure becomes a warning and the batch continues.","Verify the language actually exists in info_dict['subtitles'] / info_dict['automatic_captions'] before enabling subtitle download for that code.","For authentication-dependent subtitles, pass cookies via 'cookiefile' so the subtitle request is authorized.","Retry later if the subtitle URL was extracted long before download (URL expiry)."],"exampleFix":"# before\nydl_opts = {'writesubtitles': True, 'subtitleslangs': ['en']}\n# after: tolerate missing subs so the rest of the batch survives\nydl_opts = {'writesubtitles': True, 'subtitleslangs': ['en'], 'ignoreerrors': True}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from yt_dlp import YoutubeDL\nfrom yt_dlp.utils import DownloadError\n\nwith YoutubeDL(opts) as ydl:\n    try:\n        ydl.download([url])\n    except DownloadError as err:\n        if 'Unable to download video subtitles' in str(err):\n            log.warning('subtitles unavailable for %s: %s', url, err)  # continue batch\n        else:\n            raise","preventionTips":["Before download, check info = ydl.extract_info(url, download=False) and confirm the language exists in info['subtitles'] or info['automatic_captions'].","For batch jobs set 'ignoreerrors': True so subtitle failures downgrade to warnings.","Pass 'cookiefile' when subtitles require the same auth as the video.","Treat subtitle URLs as short-lived: avoid long gaps between extract_info and download."],"tags":["subtitles","download","network","yt-dlp","batch"],"backgroundTag":"subtitle-download-failed","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}