yt-dlp/yt-dlp · error

e

Error message

e

What it means

This is RetryManager.report_retry (yt_dlp/utils/_utils.py): the reporting hub for every yt-dlp retry loop (--retries, --fragment-retries, --extractor-retries). When attempts exceed the retry budget and no error callback was supplied, it re-raises the last exception verbatim ('raise e') - the surfaced message is the underlying network/HTTP/extractor error itself, optionally preceded by '<e>. Retrying (n/N)...' warnings and followed by nothing. With an error callback it reports '<e>. Giving up after N retries' instead of raising.

Source

Thrown at yt_dlp/utils/_utils.py:5300

    def __iter__(self):
        while self._should_retry():
            self.error = NO_DEFAULT
            self.attempt += 1
            yield self
            if self.error:
                self.error_callback(self.error, self.attempt, self.retries)

    @staticmethod
    def report_retry(e, count, retries, *, sleep_func, info, warn, error=None, suffix=None):
        """Utility function for reporting retries"""
        if count > retries:
            if error:
                return error(f'{e}. Giving up after {count - 1} retries') if count > 1 else error(str(e))
            raise e

        if not count:
            return warn(e)
        elif isinstance(e, ExtractorError):
            e = remove_end(str_or_none(e.cause) or e.orig_msg, '.')
        warn(f'{e}. Retrying{format_field(suffix, None, " %s")} ({count}/{retries})...')

        delay = float_or_none(sleep_func(n=count - 1)) if callable(sleep_func) else sleep_func
        if delay:
            info(f'Sleeping {delay:.2f} seconds ...')
            time.sleep(delay)


@partial_application
def make_archive_id(ie, video_id):
    ie_key = ie if isinstance(ie, str) else ie.ie_key()
    return f'{ie_key.lower()} {video_id}'


@partial_application
def truncate_string(s, left, right=0):

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Re-run the command - yt-dlp resumes and often completes on fresh fragment URLs
  2. Raise the budgets and add backoff: --retries 10 --fragment-retries 10 --retry-sleep linear=1:2:5 (or exponential)
  3. Check the underlying cause in the message: 403/geo -> fix headers/geo (update yt-dlp); 429 -> slow down (--limit-rate, --sleep-requests); network -> fix DNS/proxy
  4. Embedders: construct RetryManager with an error_callback so exhaustion is reported to your handler instead of raising

Example fix

Wrap the retry loop body and re-raise with context: except Exception as e: self.report_error(str(e)); continue the retry loop only while count < retries
Defensive patterns

Strategy: retry

Try / catch

from yt_dlp import YoutubeDL
from yt_dlp.utils import DownloadError

for attempt in range(3):  # outer retry around yt-dlp's own retries
    try:
        with YoutubeDL(opts) as ydl:
            ydl.download([url])
        break
    except DownloadError as e:
        logger.warning('attempt %d failed: %s', attempt + 1, e)
else:
    logger.error('gave up on %s', url)

Prevention

When it happens

Trigger: A failure persists for all attempts: dead/expired fragment URLs (404 from CDN), 429 rate limiting, geo-blocks, DNS/proxy failures, or an extractor error repeated across --extractor-retries. Each retry emits a warning line; the final raise surfaces as DownloadError/ExtractorError wrapping the original exception.

Common situations: Expired HLS/DASH manifests where fragments rot between playlist fetch and download; aggressive throttling triggering 429; flaky proxies/VPNs dropping mid-download; resuming large downloads after long pauses.

Related errors


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/5e5a21d10bb77de6. Report an issue: GitHub.