ytdl-org/youtube-dl · warning · ExtractorError

%s is not available

Error message

%s is not available

What it means

Raised by FranceTVJeunesseIE (zouzous.fr / ludo.fr hero pages) when the playlist API responds but its 'count' field is falsy — zero or missing. A zero-count playlist means the hero page has no episodes attached, so the extractor reports the playlist id as unavailable. Expected=True; a content state, not a bug.

Source

Thrown at youtube_dl/extractor/francetv.py:537

        'url': 'https://www.ludo.fr/heros/ninjago',
        'info_dict': {
            'id': 'ninjago',
        },
        'playlist_count': 10,
    }, {
        'url': 'https://www.zouzous.fr/heros/simon?abc',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        playlist_id = mobj.group('id')

        playlist = self._download_json(
            '%s/%s' % (mobj.group('url'), 'playlist'), playlist_id)

        if not playlist.get('count'):
            raise ExtractorError(
                '%s is not available' % playlist_id, expected=True)

        entries = []
        for item in playlist['items']:
            identity = item.get('identity')
            if identity and isinstance(identity, compat_str):
                entries.append(self._make_url_result(identity))

        return self.playlist_result(entries, playlist_id)

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Search the character/show on www.france.tv (zouzous/ludo content was migrated) and use the new URL
  2. Verify the hero page in a browser still lists episodes
  3. Treat 0-count heroes as permanently retired and remove them from crawl lists
  4. Update youtube-dl/yt-dlp in case the playlist endpoint moved

Example fix

# before
youtube_dl 'https://www.zouzous.fr/heros/retired-character'
# ERROR: retired-character is not available

# after
yt-dlp 'https://www.france.tv/zouzous/current-show-episode.html'
Defensive patterns

Strategy: try-catch

Validate before calling

# Pre-check playlist count before extraction
playlist = fetch_json(hero_url + '/playlist')
if not playlist.get('count'):
    skip_hero(hero_id)  # empty/retired hero page

Type guard

def has_episodes(playlist: dict) -> bool:
    return (
        isinstance(playlist, dict)
        and bool(playlist.get('count'))
        and isinstance(playlist.get('items'), list)
        and len(playlist['items']) > 0
    )

Try / catch

try:
    ydl.extract_info(url)
except ExtractorError as e:
    if str(e).endswith('is not available'):
        prune_retired_hero(url)

Prevention

When it happens

Trigger: _download_json of <hero-url>/playlist returns an object whose 'count' key is 0, null, or absent, triggering the raise. Produced by retired/zouzous hero pages whose episode sets were emptied during site restructuring.

Common situations: Kids-content archives pointing at zouzous.fr/heros/<name> pages after France TV moved children's content to france.tv; scraping all hero URLs and hitting deprecated ones.

Related errors


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