yt-dlp/yt-dlp · error · ExtractorError

This course episode is not yet available.

Error message

This course episode is not yet available.

What it means

Expected error raised by BilibiliCheeseBaseIE._extract_episode when the course episode's ep_status field equals -1. Cheese (pugv) courses publish episode metadata ahead of release; ep_status == -1 marks an episode that has not aired/been unlocked yet, so the extractor fails fast instead of calling the playurl API for media that cannot exist.

Source

Thrown at yt_dlp/extractor/bilibili.py:1202

        webpage = self._download_webpage(url, ss_id)
        metainfo = traverse_obj(
            self._search_json(r'<script[^>]+type="application/ld\+json"[^>]*>', webpage, 'info', ss_id),
            ('itemListElement', ..., {
                'title': ('name', {str}),
                'description': ('description', {str}),
            }), get_all=False)

        return self.playlist_result(self._get_episodes_from_season(ss_id, url), ss_id, **metainfo)


class BilibiliCheeseBaseIE(BilibiliBaseIE):
    def _extract_episode(self, season_info, ep_id):
        episode_info = traverse_obj(season_info, (
            'episodes', lambda _, v: v['id'] == int(ep_id)), get_all=False)
        aid, cid = episode_info['aid'], episode_info['cid']

        if traverse_obj(episode_info, 'ep_status') == -1:
            raise ExtractorError('This course episode is not yet available.', expected=True)
        if not traverse_obj(episode_info, 'playable'):
            self.raise_login_required('You need to purchase the course to download this episode')

        play_info = self._download_json(
            'https://api.bilibili.com/pugv/player/web/playurl', ep_id,
            query={'avid': aid, 'cid': cid, 'ep_id': ep_id, 'fnval': 16, 'fourk': 1},
            headers=self._HEADERS, note='Downloading playinfo')['data']

        return {
            'id': str_or_none(ep_id),
            'episode_id': str_or_none(ep_id),
            'formats': self.extract_formats(play_info),
            'extractor_key': BilibiliCheeseIE.ie_key(),
            'extractor': BilibiliCheeseIE.IE_NAME,
            'webpage_url': f'https://www.bilibili.com/cheese/play/ep{ep_id}',
            **traverse_obj(episode_info, {
                'episode': ('title', {str}),
                'title': {lambda v: v and join_nonempty('index', 'title', delim=' - ', from_dict=v)},

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Check the episode list on bilibili.com — episodes with a future unlock time are not fetchable; retry after the scheduled release.
  2. Restrict your download to published episodes (e.g. --playlist-items with the aired range).
  3. If the episode is visibly playable in a browser, update yt-dlp and report it (the ep_status semantics may have changed).
Defensive patterns

Strategy: validation

Validate before calling

# if you already have the season_info JSON (e.g. via API wrapper)
ep = next(e for e in season_info['episodes'] if e['id'] == int(ep_id))
if ep.get('ep_status') == -1:
    schedule_retry_after_release(ep.get('publish_time'), ep_id)  # skip for now

Type guard

def cheese_episode_ready(ep) -> bool:
    return isinstance(ep, dict) and ep.get('ep_status') != -1 and ep.get('playable')

Try / catch

try:
    info = ydl.extract_info(url, download=False)
except ExtractorError as e:
    if 'not yet available' in str(e):
        schedule_retry(url, after=release_date)  # scheduled content; not an error
    else:
        raise

Prevention

When it happens

Trigger: Downloading a full Cheese course playlist where later episodes are scheduled but not yet published; direct ep URLs for pre-announced episodes; episodes gated behind a course start date.

Common situations: Batch archiving a course on day one; users misreading 'coming soon' episode entries as available; timezone confusion about release times.

Related errors


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