jackwener/OpenCLI · warning · EmptyResultError

youtube transcript

Error message

youtube transcript

What it means

After all extraction strategies (player extraction, network capture, caption XML fetch) the segments command requires at least one segment. If the final segments array is empty, it throws EmptyResultError('youtube transcript') — signaling a legitimate empty transcript outcome (code EMPTY_RESULT), which downstream logic treats as skip-worthy rather than a retryable failure.

Source

Thrown at clis/youtube/transcript.js:562

          // Strip inner tags (e.g. <s> in srv3 format) and decode entities
          const text = decodeEntities(content.replace(/<[^>]+>/g, '')).split('\\\\n').join(' ').trim();
          if (text) {
            results.push({ start: startSec, end: startSec + durSec, text });
          }

          pos = tagEnd + endMarker.length;
        }

        if (results.length === 0) {
          return { error: 'Parsed 0 segments from caption XML' };
        }

        return results;
      })()
    `), 'caption XML extraction');
        }
        if (segments.length === 0) {
            throw new EmptyResultError('youtube transcript');
        }
        // Step 3: Fetch chapters (for grouped mode)
        let chapters = [];
        if (mode === 'grouped') {
            try {
                const chapterData = unwrapBrowserResult(await page.evaluate(`
          (async () => {
            const cfg = window.ytcfg?.data_ || {};
            const apiKey = cfg.INNERTUBE_API_KEY;
            if (!apiKey) return [];

            const resp = await fetch('/youtubei/v1/next?key=' + apiKey + '&prettyPrint=false', {
              method: 'POST',
              credentials: 'include',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({
                context: { client: { clientName: 'WEB', clientVersion: '2.20240101.00.00' } },
                videoId: ${JSON.stringify(videoId)}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Catch EmptyResultError and treat the video as having no transcript — skip retries and softFail counting.
  2. Retry later if the video is very new (auto-captions can take time to generate).
  3. Verify in the YouTube UI whether a CC track exists and has content.
  4. If empty results cluster unexpectedly, check for a CLI/YouTube schema mismatch breaking all parse paths.

Example fix

// before
const results = await transcript(videoId); // throws on empty
// after
try {
  const results = await transcript(videoId);
} catch (err) {
  if (err instanceof EmptyResultError) return [];
  throw err;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const segments = await getSegments(videoId);
  if (segments.length === 0) return []; // defensive
} catch (err) {
  if (err instanceof EmptyResultError) return []; // no transcript available
  throw err;
}

Prevention

When it happens

Trigger: `segments` completes every extraction path but each yields zero rows — e.g. a caption track exists but contains no timed events, or every fallback returned empty arrays.

Common situations: Videos whose caption track is present but empty; captions that fail to yield parseable events after YouTube schema drift; auto-captions not yet generated for freshly uploaded videos.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/0436188b134d7712. Report an issue: GitHub.