{"record":{"id":"075a07811e577bf7","repo":"unslothai/unsloth","slug":"could-not-reach-youtube","errorCode":null,"errorMessage":"Could not reach YouTube.","messagePattern":"Could not reach YouTube\\.","errorType":"http","errorClass":"HTTPException","httpStatus":502,"severity":"error","filePath":"studio/backend/routes/youtube.py","lineNumber":65,"sourceCode":"    text: str\n    truncated: bool\n\n\n@router.post(\"/transcript\", response_model = TranscriptResponse)\nasync def get_transcript(\n    request: TranscriptRequest, current_subject: str = Depends(get_current_subject)\n) -> TranscriptResponse:\n    video_id = extract_video_id(request.url)\n    if video_id is None:\n        raise HTTPException(status_code = 400, detail = \"That is not a YouTube video link.\")\n\n    try:\n        transcript = await fetch_transcript(video_id, request.languages)\n    except TranscriptUnavailable as error:\n        raise HTTPException(status_code = 422, detail = str(error)) from error\n    except httpx.HTTPError as error:\n        logger.warning(f\"YouTube transcript fetch failed for {video_id}: {error}\")\n        raise HTTPException(\n            status_code = 502,\n            detail = \"Could not reach YouTube.\",\n        ) from error\n\n    return TranscriptResponse(\n        videoId = transcript.video_id,\n        url = watch_url(transcript.video_id),\n        title = transcript.title,\n        author = transcript.author,\n        lengthSeconds = transcript.length_seconds,\n        language = transcript.language,\n        languageCode = transcript.language_code,\n        isGenerated = transcript.is_generated,\n        text = transcript.text,\n        truncated = transcript.truncated,\n    )\n","sourceCodeStart":47,"sourceCodeEnd":82,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/youtube.py#L47-L82","documentation":"502 from POST /youtube/transcript: fetch_transcript failed with an httpx.HTTPError — the outbound HTTP layer could not complete requests to YouTube (DNS failure, connection refused/reset, TLS error, or timeout). The backend logs the specifics ('YouTube transcript fetch failed for <id>') and maps it to a gateway-style 502 because the failure is upstream, not in the request itself.","triggerScenarios":"Studio host has no internet or a blocking firewall/proxy; YouTube returns RSTs / rate-limits the IP; corporate MITM proxy with an untrusted CA breaks TLS; transient network blip during fetch.","commonSituations":"Air-gapped or proxied dev environments; heavy polling from one IP triggering throttling; DNS misconfiguration in a container.","solutions":["Verify egress: curl https://www.youtube.com from the same host.","Configure proxy env vars (HTTPS_PROXY) or the proxy's CA in httpx if behind a corporate proxy.","Retry after a short backoff — many occurrences are transient throttles.","Check the server log line for the precise httpx error class (ConnectError vs ReadTimeout guides the fix)."],"exampleFix":"// client: bounded retry with backoff\nfor (let i = 0; i < 3; i++) {\n  try { return await api.post('/youtube/transcript', { url }); }\n  catch (e) { if (e.status !== 502 || i === 2) throw e; await sleep(2 ** i * 1000); }\n}","handlingStrategy":"retry","validationCode":"// client-side reachability probe before the call (optional)\nconst online = typeof navigator === 'undefined' ? true : navigator.onLine;\nif (!online) throw new Error('You appear to be offline.');","typeGuard":null,"tryCatchPattern":"async function withRetry(fn, attempts = 3) {\n  for (let i = 0; ; i++) {\n    try { return await fn(); }\n    catch (e) {\n      if (e?.status !== 502 || i >= attempts - 1) throw e;\n      await new Promise(r => setTimeout(r, 2 ** i * 1000));\n    }\n  }\n}","preventionTips":["Apply exponential-backoff retry only to 502 (upstream/network), not 4xx","Configure HTTPS_PROXY/CA for corporate networks on the backend host","Check the backend log for the underlying httpx error class before assuming code fault"],"tags":["http-502","httpx","network","youtube","proxy","rate-limit"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}