danielmiessler/Fabric · error · Error

errorData.error || 'Failed to fetch transcript'

Error message

errorData.error || 'Failed to fetch transcript'

What it means

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.

Source

Thrown at web/src/lib/components/chat/Transcripts.svelte:40

      return;
    }

    loading = true;
    error = '';

    try {
      const response = await fetch('/chat', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        },
        body: JSON.stringify({ url })
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.error || 'Failed to fetch transcript');
      }

      const data = await response.json();
      console.log('Parsed response data:', data);

      transcript = data.transcript;
      title = data.title;

    } finally {
      loading = false;
    }
  }

  async function copyToClipboard() {
    try {
      await navigator.clipboard.writeText(transcript);
      toastStore.success('Transcript copied to clipboard!');
    } catch (err) {

View on GitHub (pinned to 338b89cfe9)

Solutions

  1. Read errorData.error in the Network tab — it distinguishes 'no captions' from 'fetch blocked' from 'invalid URL'
  2. Test the same URL in a browser: confirm the video exists, is public, and has captions enabled
  3. Update the server-side transcript extraction library to the latest patch (these break frequently as YouTube changes)
  4. If the server IP is blocked, run behind a different egress or configure cookies/headers the extractor accepts
  5. Guard response.json() so HTML error pages don't surface as JSON parse failures

Example fix

// before
if (!response.ok) {
  const errorData = await response.json();
  throw new Error(errorData.error || 'Failed to fetch transcript');
}

// after
if (!response.ok) {
  const errorData = await response.json().catch(() => null);
  throw new Error(errorData?.error || `Failed to fetch transcript (HTTP ${response.status})`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Basic URL sanity before the request
const yt = new URL(url); // throws TypeError on malformed input
if (!/^(www\.)?(youtube\.com|youtu\.be)$/i.test(yt.hostname.replace(/^m\./i, ''))) {
  throw new Error('Please provide a YouTube URL');
}

Try / catch

try {
  const response = await fetch('/chat', { method: 'POST', headers: {...}, body: JSON.stringify({ url }) });
  if (!response.ok) {
    const errorData = await response.json().catch(() => null);
    throw new Error(errorData?.error || `Failed to fetch transcript (HTTP ${response.status})`);
  }
  const data = await response.json();
  transcript = data.transcript;
  title = data.title;
} catch (error) {
  console.error('Transcript fetch failed:', error);
  throw error;
} finally {
  loading = false;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of danielmiessler/Fabric@338b89cfe9 (2026-08-15). Data as JSON: /api/errors/e109a3bbdba64abc. Report an issue: GitHub.