unslothai/unsloth · error · TranscriptUnavailable

That is not a YouTube video link.

Error message

That is not a YouTube video link.

What it means

TranscriptUnavailable raised by fetch_transcript when the video_id argument does not fullmatch the YouTube video id regex (_VIDEO_ID_RE, the 11-character [-A-Za-z0-9_] id format). The function takes a bare video id, not a URL, so passing a full watch URL or a malformed id fails this check before any network call.

Source

Thrown at studio/backend/core/youtube_transcript.py:110

        for prefix in _ID_PATH_PREFIXES:
            if parsed.path.startswith(prefix):
                candidate = parsed.path[len(prefix) :].split("/", 1)[0]
                break
    return candidate if _VIDEO_ID_RE.fullmatch(candidate) else None


def watch_url(video_id: str) -> str:
    return f"https://www.youtube.com/watch?v={video_id}"


async def fetch_transcript(video_id: str, languages: Sequence[str] = ()) -> Transcript:
    """Download the captions for ``video_id``, preferring ``languages`` in order.

    Within a language a human-written track wins over an auto-generated one. With no
    match the track YouTube pairs with the video's default audio track is used.
    """
    if not _VIDEO_ID_RE.fullmatch(video_id):
        raise TranscriptUnavailable("That is not a YouTube video link.")

    async with httpx.AsyncClient(timeout = _TIMEOUT, follow_redirects = True) as client:
        player = await _fetch_player(client, video_id)
        status = (player.get("playabilityStatus") or {}).get("status")
        if status not in (None, "OK"):
            raise TranscriptUnavailable(
                (player.get("playabilityStatus") or {}).get("reason")
                or "YouTube will not play this video."
            )

        tracklist = (player.get("captions") or {}).get("playerCaptionsTracklistRenderer") or {}
        tracks = [t for t in (tracklist.get("captionTracks") or []) if t.get("baseUrl")]
        if not tracks:
            raise TranscriptUnavailable("This video has no captions.")

        track = _select_track(tracks, tracklist, languages)
        text = await _fetch_track_text(client, str(track["baseUrl"]))

View on GitHub (pinned to 203007d190)

Solutions

  1. Extract the 11-character video id before calling (e.g. re.search(r'(?:v=|youtu\.be/|/shorts/)([A-Za-z0-9_-]{11})', url)).
  2. Strip whitespace from the id.
  3. If you control upstream, validate the id with the same pattern before dispatching the request.

Example fix

# before
transcript = await fetch_transcript("https://www.youtube.com/watch?v=dQw4w9WgXcQ")

# after
import re
match = re.search(r"(?:v=|youtu\.be/|/shorts/)([A-Za-z0-9_-]{11})", url)
transcript = await fetch_transcript(match.group(1)) if match else None
Defensive patterns

Strategy: validation

Validate before calling

import re

_VIDEO_ID_RE = re.compile(r"^[A-Za-z0-9_-]{11}$")

def extract_video_id(url_or_id: str) -> str | None:
    s = url_or_id.strip()
    if _VIDEO_ID_RE.fullmatch(s):
        return s
    m = re.search(r"(?:v=|youtu\.be/|/shorts/|/embed/)([A-Za-z0-9_-]{11})", s)
    return m.group(1) if m else None

video_id = extract_video_id(user_input)
if video_id is None:
    return "Please provide a valid YouTube link or 11-character video id."

Type guard

def is_youtube_video_id(value: str) -> bool:
    import re
    return bool(re.fullmatch(r"[A-Za-z0-9_-]{11}", value.strip()))

Try / catch

try:
    transcript = await fetch_transcript(video_id)
except TranscriptUnavailable as e:
    if "not a YouTube video link" in str(e):
        return bad_request_error(str(e))
    raise

Prevention

When it happens

Trigger: Calling fetch_transcript with a full URL such as 'https://www.youtube.com/watch?v=abc' instead of the 11-char id; passing a youtu.be short link; passing an extracted id that includes whitespace, query params, or is the wrong length/charset.

Common situations: Caller forgets to run the id through an extractor/regex before calling; ids copied with trailing newline or spaces; shorts URLs parsed incorrectly.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/86646b0c8020e8ec. Report an issue: GitHub.