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
- Re-run the command - yt-dlp resumes and often completes on fresh fragment URLs
- Raise the budgets and add backoff: --retries 10 --fragment-retries 10 --retry-sleep linear=1:2:5 (or exponential)
- 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
- 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
- Set generous budgets upfront: 'retries', 'fragment_retries', 'extractor_retries' in opts or --retries/--fragment-retries on CLI
- Add backoff via 'retry_sleep_functions' (or --retry-sleep exponential) instead of default fixed delays
- For long downloads, re-run the same command to resume from .part files instead of starting over
- Watch for 429s and throttle with --limit-rate / --sleep-requests rather than only raising retries
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
- {e}. Retrying{format_field(suffix, None, " %s")} ({count}/{r
- Unable to download video subtitles for {sub_lang!r}: {err}
- Impersonate target "{impersonate_target}" is not available.
- Invalid js_runtimes format, expected a dict of {runtime: {co
- Wrong regex for allowed_extractors: {e.pattern}
AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22).
Data as JSON: /api/errors/5e5a21d10bb77de6.
Report an issue: GitHub.