{"record":{"id":"e109a3bbdba64abc","repo":"danielmiessler/Fabric","slug":"errordata-error-failed-to-fetch-transcript","errorCode":null,"errorMessage":"errorData.error || 'Failed to fetch transcript'","messagePattern":"errorData\\.error \\|\\| 'Failed to fetch transcript'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/lib/components/chat/Transcripts.svelte","lineNumber":40,"sourceCode":"      return;\n    }\n\n    loading = true;\n    error = '';\n\n    try {\n      const response = await fetch('/chat', {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          'Accept': 'application/json'\n        },\n        body: JSON.stringify({ url })\n      });\n\n      if (!response.ok) {\n        const errorData = await response.json();\n        throw new Error(errorData.error || 'Failed to fetch transcript');\n      }\n\n      const data = await response.json();\n      console.log('Parsed response data:', data);\n\n      transcript = data.transcript;\n      title = data.title;\n\n    } finally {\n      loading = false;\n    }\n  }\n\n  async function copyToClipboard() {\n    try {\n      await navigator.clipboard.writeText(transcript);\n      toastStore.success('Transcript copied to clipboard!');\n    } catch (err) {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/danielmiessler/Fabric/blob/338b89cfe97ab2d12ce30ce8b5449857a841366d/web/src/lib/components/chat/Transcripts.svelte#L22-L58","documentation":"Thrown in Transcripts.svelte when POST /chat (with a URL payload) returns non-ok while fetching a YouTube transcript. The server-side transcript fetcher failed — common causes are an invalid/unavailable video URL, the video having no captions, YouTube blocking/rate-limiting the server's request, or the extract/transcript library being out of date. errorData.error carries the server's reason when the endpoint returns JSON.","triggerScenarios":"Submitting a non-YouTube URL or malformed link; a video with captions disabled; YouTube returning a consent/bot check to the server IP; the transcript library version no longer matching YouTube's page structure; the downstream Fabric call inside the same endpoint failing and the endpoint mapping it to a generic error.","commonSituations":"yt-dlp / youtube-transcript-api style libraries breaking after YouTube site changes, corporate IPs getting rate-limited, missing cookies for age-restricted videos, dev proxy interfering with the POST.","solutions":["Read errorData.error in the Network tab — it distinguishes 'no captions' from 'fetch blocked' from 'invalid URL'","Test the same URL in a browser: confirm the video exists, is public, and has captions enabled","Update the server-side transcript extraction library to the latest patch (these break frequently as YouTube changes)","If the server IP is blocked, run behind a different egress or configure cookies/headers the extractor accepts","Guard response.json() so HTML error pages don't surface as JSON parse failures"],"exampleFix":"// before\nif (!response.ok) {\n  const errorData = await response.json();\n  throw new Error(errorData.error || 'Failed to fetch transcript');\n}\n\n// after\nif (!response.ok) {\n  const errorData = await response.json().catch(() => null);\n  throw new Error(errorData?.error || `Failed to fetch transcript (HTTP ${response.status})`);\n}","handlingStrategy":"try-catch","validationCode":"// Basic URL sanity before the request\nconst yt = new URL(url); // throws TypeError on malformed input\nif (!/^(www\\.)?(youtube\\.com|youtu\\.be)$/i.test(yt.hostname.replace(/^m\\./i, ''))) {\n  throw new Error('Please provide a YouTube URL');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const response = await fetch('/chat', { method: 'POST', headers: {...}, body: JSON.stringify({ url }) });\n  if (!response.ok) {\n    const errorData = await response.json().catch(() => null);\n    throw new Error(errorData?.error || `Failed to fetch transcript (HTTP ${response.status})`);\n  }\n  const data = await response.json();\n  transcript = data.transcript;\n  title = data.title;\n} catch (error) {\n  console.error('Transcript fetch failed:', error);\n  throw error;\n} finally {\n  loading = false;\n}","preventionTips":["Validate the URL shape client-side before hitting the endpoint","Keep the transcript-extraction library patched — YouTube changes break it regularly","Treat 4xx from this endpoint as user errors (bad URL / no captions) and 5xx as extraction failures so retry guidance is accurate"],"tags":["youtube","transcript","http","scraping"],"backgroundTag":null,"analyzedSha":"338b89cfe97ab2d12ce30ce8b5449857a841366d","analyzedAt":"2026-08-15T11:38:51.759Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}