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
- Extract the 11-character video id before calling (e.g. re.search(r'(?:v=|youtu\.be/|/shorts/)([A-Za-z0-9_-]{11})', url)).
- Strip whitespace from the id.
- 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
- Always extract the 11-char id from URLs before calling fetch_transcript.
- Strip whitespace/newlines from user-supplied ids.
- Validate ids client-side with the same regex pattern.
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
- load timed out (last progress: {prog})
- YouTube will not play this video.
- This video has no captions.
- This video's captions are empty.
- YouTube returned an unreadable response.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/86646b0c8020e8ec.
Report an issue: GitHub.