ytdl-org/youtube-dl · warning · ExtractorError

Test case %d not found, got only %d tests

Error message

Test case %d not found, got only %d tests

What it means

Raised by the testurl extractor when the optional /<num> index in testurl:<extractor>/<num> is out of range: after collecting the extractor's _TEST (singular) plus all _TESTS entries, testcases[num] raised IndexError. The error reports the requested index and how many tests actually exist. Marked expected=True.

Source

Thrown at youtube_dl/extractor/testurl.py:57

                    ('Found multiple matching extractors: %s' %
                        ' '.join(ie.IE_NAME for ie in matching_extractors)),
                    expected=True)
        else:
            extractor = matching_extractors[0]

        num_str = mobj.group('num')
        num = int(num_str) if num_str else 0

        testcases = []
        t = getattr(extractor, '_TEST', None)
        if t:
            testcases.append(t)
        testcases.extend(getattr(extractor, '_TESTS', []))

        try:
            tc = testcases[num]
        except IndexError:
            raise ExtractorError(
                ('Test case %d not found, got only %d tests' %
                    (num, len(testcases))),
                expected=True)

        self.to_screen('Test URL: %s' % tc['url'])

        return self.url_result(tc['url'], video_id=video_id)

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Use a smaller index: the message states 'got only %d tests', so valid indices are 0..that-1.
  2. Omit the index entirely (testurl:<name>) to get the extractor's primary test case.
  3. Regenerate any hard-coded indices after upgrading youtube-dl, since test lists change between versions.

Example fix

# before (5 tests => indices 0..4)
# youtube-dl testurl:someextractor/5
# after
# youtube-dl testurl:someextractor/4   # or simply:
# youtube-dl testurl:someextractor
Defensive patterns

Strategy: validation

Validate before calling

# Determine how many tests an extractor exposes before choosing an index
ie = next(e for e in gen_extractors() if e.IE_NAME.lower() == name.lower())
count = (1 if getattr(ie, '_TEST', None) else 0) + len(getattr(ie, '_TESTS', []))
if not 0 <= num < count:
    print('index %d out of range; valid: 0..%d' % (num, count - 1))

Type guard

def valid_test_index(ie, num):
    """True when num indexes into the extractor's collected test cases."""
    total = (1 if getattr(ie, '_TEST', None) else 0) + len(getattr(ie, '_TESTS', []))
    return isinstance(num, int) and 0 <= num < total

Try / catch

try:
    ydl.extract_info('testurl:%s/%d' % (name, num))
except ExtractorError as e:
    if e.expected and 'not found, got only' in str(e):
        num = 0  # fall back to the primary test case
        ydl.extract_info('testurl:%s' % name)
    else:
        raise

Prevention

When it happens

Trigger: A URL like testurl:youtube/99 when the matched extractor has fewer than 100 test cases; note indices are 0-based, so testurl:<name>/<N> fails once N >= number of tests (num defaults to 0 when omitted).

Common situations: Off-by-one confusion (asking for test 5 on an extractor with 5 tests — valid indices are 0..4); hard-coded test indices in scripts that break when an extractor's _TESTS list shrinks in a new release.

Related errors


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