unslothai/unsloth · error · HTTPException

str(error)

Error message

str(error)

What it means

422 from POST /youtube/transcript: fetch_transcript raised TranscriptUnavailable and the 422 detail is that exception's message. This covers YouTube-side content problems the service distinguishes from network failure: no captions exist for the video, captions exist but none match the requested languages, auto-generated captions are disabled, or the video is private/age-restricted/removed.

Source

Thrown at studio/backend/routes/youtube.py:62

    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,
        language = transcript.language,
        languageCode = transcript.language_code,
        isGenerated = transcript.is_generated,
        text = transcript.text,
        truncated = transcript.truncated,

View on GitHub (pinned to 203007d190)

Solutions

  1. Read the detail message — it states which case applied (no captions vs language mismatch).
  2. Retry without the languages filter to accept any available track.
  3. Verify the video is public and has captions (CC button on YouTube's own player).
  4. If captions genuinely don't exist, no fix is possible — pick another source video.

Example fix

// before
await api.post('/youtube/transcript', { url, languages: ['de'] });

// after
try {
  await api.post('/youtube/transcript', { url, languages: ['de'] });
} catch (e) if (e.status === 422) {
  // fall back to any available language
  await api.post('/youtube/transcript', { url });
}
Defensive patterns

Strategy: fallback

Try / catch

try {
  return await api.post('/youtube/transcript', { url, languages });
} catch (e) {
  if (e.status === 422 && languages?.length) {
    // language miss: accept any available track
    return await api.post('/youtube/transcript', { url });
  }
  throw e;
}

Prevention

When it happens

Trigger: Requesting a video with captions disabled by the uploader; requesting languages=['de'] for an English-only video; private/unlisted video whose transcript endpoint returns no body; auto-caption still processing for a just-uploaded video.

Common situations: Music videos and game captures (captions routinely absent); non-matching language preference lists; freshly uploaded videos.

Related errors


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