ytdl-org/youtube-dl · error · ExtractorError

Giving up retrying

Error message

Giving up retrying

What it means

Raised by multipart_encode/_multipart_encode_impl when the chosen multipart boundary string appears inside a form field's name or value, which would corrupt the framing (a receiver would split the body at the wrong place). The library deliberately scans each encoded part for the boundary bytes and aborts rather than emitting an ambiguous body.

Source

Thrown at youtube_dl/extractor/adn.py:227

                    })
                break
            except ExtractorError as e:
                if not isinstance(e.cause, compat_HTTPError):
                    raise e

                if e.cause.code == 401:
                    # This usually goes away with a different random pkcs1pad, so retry
                    continue

                error = self._parse_json(
                    self._webpage_read_content(e.cause, links_url, video_id),
                    video_id, fatal=False) or {}
                message = error.get('message')
                if e.cause.code == 403 and error.get('code') == 'player-bad-geolocation-country':
                    self.raise_geo_restricted(msg=message)
                raise ExtractorError(message)
        else:
            raise ExtractorError('Giving up retrying')

        links = links_data.get('links') or {}
        metas = links_data.get('metadata') or {}
        sub_url = (links.get('subtitles') or {}).get('all')
        video_info = links_data.get('video') or {}
        title = metas['title']

        formats = []
        for format_id, qualities in (links.get('streaming') or {}).items():
            if not isinstance(qualities, dict):
                continue
            for quality, load_balancer_url in qualities.items():
                load_balancer_data = self._download_json(
                    load_balancer_url, video_id,
                    'Downloading %s %s JSON metadata' % (format_id, quality),
                    fatal=False) or {}
                m3u8_url = load_balancer_data.get('location')
                if not m3u8_url:

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Omit the boundary argument and let multipart_encode generate a random one (it uses uuid-based generation).
  2. Use a long, high-entropy boundary (e.g. '----------aBcXyZ1234567890$') unlikely to occur in any field.
  3. If the server requires an exact boundary, sanitize or base64-encode field values that might contain it.
  4. Catch ValueError at the call site and regenerate a new random boundary before retrying once.

Example fix

# before
body, ct = multipart_encode(data, boundary='----WebKitFormBoundaryx')

# after: auto-generate a collision-free boundary
body, ct = multipart_encode(data)  # random uuid4-based boundary

# or regenerate on collision
import uuid
while True:
    try:
        body, ct = multipart_encode(data, boundary=uuid.uuid4().hex)
        break
    except ValueError:
        continue
Defensive patterns

Strategy: retry

Validate before calling

import uuid

def safe_multipart_encode(data, boundary=None):
    from youtube_dl.utils import multipart_encode
    for _ in range(5):
        b = boundary or uuid.uuid4().hex
        collisions = [k for k, v in data.items() if b.encode('ascii')
                      in str(k).encode('utf-8') + str(v).encode('utf-8')]
        if not collisions:
            return multipart_encode(data, boundary=b)
        boundary = None  # regenerate
    raise ValueError('could not find a non-colliding boundary')

Try / catch

from youtube_dl.utils import multipart_encode
import uuid
for _ in range(5):
    try:
        body, ct = multipart_encode(data, boundary=uuid.uuid4().hex)
        break
    except ValueError as e:
        if 'Boundary overlaps with data' not in str(e):
            raise
else:
    raise ValueError('boundary kept colliding with payload')

Prevention

When it happens

Trigger: Calling multipart_encode(data, boundary=...) with a boundary that is a substring of any value (or field name) in data. With a random default boundary this is astronomically unlikely; it happens when callers pass a fixed/short boundary like 'boundary' or '----x' and upload text content containing that token.

Common situations: Reusing a hard-coded boundary from a captured browser request whose body content later includes the same string; very short boundaries colliding with binary-ish payloads; API clients mirroring a server's expected boundary without validating against content.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/208ce188429dbbfa. Report an issue: GitHub.