yt-dlp/yt-dlp · error · ExtractorError

Invalid extractor-arg "tab". Must be one of {", ".join(self.

Error message

Invalid extractor-arg "tab". Must be one of {", ".join(self._TABS)}

What it means

Rokfin's channel extractor validates the 'tab' extractor-arg in _validate_extractor_args before any network request: the argument must be a single value from the allowed set (the _TABS keys: videos, podcasts, streams, stacks). Passing more than one tab or an unknown name raises this immediately with expected=True.

Source

Thrown at yt_dlp/extractor/rokfin.py:355

        },
    }]

    _TABS = {
        'new': 'posts',
        'top': 'top',
        'videos': 'video',
        'podcasts': 'audio',
        'streams': 'stream',
        'stacks': 'stack',
    }

    def _real_initialize(self):
        self._validate_extractor_args()

    def _validate_extractor_args(self):
        requested_tabs = self._configuration_arg('tab', None)
        if requested_tabs is not None and (len(requested_tabs) > 1 or requested_tabs[0] not in self._TABS):
            raise ExtractorError(f'Invalid extractor-arg "tab". Must be one of {", ".join(self._TABS)}', expected=True)

    def _entries(self, channel_id, channel_name, tab):
        pages_total = None
        for page_n in itertools.count(0):
            if tab in ('posts', 'top'):
                data_url = f'{_API_BASE_URL}user/{channel_name}/{tab}?page={page_n}&size=50'
            else:
                data_url = f'{_API_BASE_URL}post/search/{tab}?page={page_n}&size=50&creator={channel_id}'
            metadata = self._download_json(
                data_url, channel_name,
                note=f'Downloading video metadata page {page_n + 1}{format_field(pages_total, None, " of %s")}')

            yield from self._get_video_data(metadata)
            pages_total = int_or_none(metadata.get('totalPages')) or None
            is_last = metadata.get('last')
            if is_last or (page_n > pages_total if pages_total else is_last is not False):
                return

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Use exactly one allowed value: --extractor-args 'rokfinchannel:tab=videos' (or podcasts, streams, stacks)
  2. Pass only one tab per invocation; run the command again for each additional tab
  3. Check the value against the allowed list printed in the error message itself
  4. Update yt-dlp — new tabs are added to _TABS over time

Example fix

# before
yt-dlp --extractor-args "rokfinchannel:tab=videos;tab=streams" "https://rokfin.com/@Styxhexenhammer666"
# after
yt-dlp --extractor-args "rokfinchannel:tab=videos" "https://rokfin.com/@Styxhexenhammer666"
yt-dlp --extractor-args "rokfinchannel:tab=streams" "https://rokfin.com/@Styxhexenhammer666"
Defensive patterns

Strategy: validation

Validate before calling

ROKFIN_TABS = ('videos', 'podcasts', 'streams', 'stacks')

def build_rokfin_args(tabs):
    assert len(tabs) == 1, 'pass exactly one tab'
    assert tabs[0] in ROKFIN_TABS, f'tab must be one of {ROKFIN_TABS}'
    return ['--extractor-args', f'rokfinchannel:tab={tabs[0]}']

Type guard

def is_valid_rokfin_tab(tab: str) -> bool:
    return tab in {'videos', 'podcasts', 'streams', 'stacks'}

Prevention

When it happens

Trigger: Invoking a https://rokfin.com/@<channel> URL with --extractor-args where tab is repeated ('tab=videos;tab=streams' yields len > 1) or the value is not in _TABS (e.g. 'tab=all', 'tab=top', 'tab=live').

Common situations: Guessing tab names from the website navigation; copy-pasting multi-value extractor-arg syntax from other extractors; shell quoting that splits the argument into multiple values; scripts templating tab names from user input.

Related errors


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