unslothai/unsloth · warning · HTTPException
That is not a YouTube video link.
Error message
That is not a YouTube video link.
What it means
400 from POST /api/youtube/transcript: extract_video_id(request.url) returned None, so the submitted URL does not contain a recognizable YouTube video id (watch?v=, youtu.be/<id>, shorts, embed forms). The parser is strict about the hosts and query shapes it accepts.
Source
Thrown at studio/backend/routes/youtube.py:57
videoId: str
url: str
title: str
author: str
lengthSeconds: int
language: str
languageCode: str
isGenerated: bool
text: str
truncated: bool
@router.post("/transcript", response_model = TranscriptResponse)
async def get_transcript(
request: TranscriptRequest, current_subject: str = Depends(get_current_subject)
) -> TranscriptResponse:
video_id = extract_video_id(request.url)
if video_id is None:
raise HTTPException(status_code = 400, detail = "That is not a YouTube video link.")
try:
transcript = await fetch_transcript(video_id, request.languages)
except TranscriptUnavailable as error:
raise HTTPException(status_code = 422, detail = str(error)) from error
except httpx.HTTPError as error:
logger.warning(f"YouTube transcript fetch failed for {video_id}: {error}")
raise HTTPException(
status_code = 502,
detail = "Could not reach YouTube.",
) from error
return TranscriptResponse(
videoId = transcript.video_id,
url = watch_url(transcript.video_id),
title = transcript.title,
author = transcript.author,
lengthSeconds = transcript.length_seconds,View on GitHub (pinned to 203007d190)
Solutions
- Use a canonical URL: https://www.youtube.com/watch?v=<11-char-id> or https://youtu.be/<id>.
- Validate client-side before posting (regex for the 11-char id pattern).
- If a legitimate YouTube URL shape fails, extract the id yourself and build the canonical form before sending.
Example fix
// before
await api.post('/youtube/transcript', { url: rawPaste });
// after
const m = rawPaste.match(/(?:v=|youtu\.be\/|shorts\/)([\w-]{11})/);
if (!m) return showError('Paste a YouTube video link');
await api.post('/youtube/transcript', { url: `https://www.youtube.com/watch?v=${m[1]}` }); Defensive patterns
Strategy: validation
Validate before calling
const YT = /(?:youtube\.com\/(?:watch\?v=|shorts\/|embed\/)|youtu\.be\/)([\w-]{11})/;
function extractOrReject(url) {
const m = url?.match(YT);
if (!m) throw new ValidationError('That is not a YouTube video link.');
return m[1];
} Type guard
function isYouTubeUrl(u: string): boolean {
try { const h = new URL(u).hostname; return h === 'youtu.be' || h.endsWith('youtube.com'); }
catch { return false; }
} Try / catch
try { await postTranscript(url); }
catch (e) { if (e?.status === 400) showFieldError('Paste a YouTube video link (watch?v=… or youtu.be/…)'); else throw e; } Prevention
- Validate the URL client-side and show which video was parsed (thumbnail/id) before submit
- Normalize to canonical watch?v= form before posting
- Reject playlist/channel/search URLs early with a targeted message
When it happens
Trigger: Posting a channel or playlist URL, a bare video id without a URL, a clipboard artifact ('https://youtube.com/watch?v=abc '), a different service's link (vimeo/tiktok), or a URL with the v param stripped by a chat client's link unfurler.
Common situations: Paste-from-chat mangling; users pasting a search-results URL; frontend not validating before submit.
Related errors
- Provider base URL is malformed.
- Provider base URL must contain a hostname.
- Invalid repo_id: {repo_id!r}
- Unsupported local dataset directory (expected parquet/json/j
- Unsupported file format: {dataset_path.suffix}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/783a067670025e8b.
Report an issue: GitHub.