jackwener/OpenCLI · error · CommandExecutionError

`Failed to get caption info: ${typeof captionData === 'strin

Error message

`Failed to get caption info: ${typeof captionData === 'string' ? captionData : 'malformed response'}`

What it means

Before trusting the caption info collected from the page, the segments command checks that captionData is a non-null, non-array object. If it is a string (an in-page error message) or any other malformed shape, this error reports either the string itself or 'malformed response'. It guards the boundary between the injected page script and the Node CLI.

Source

Thrown at clis/youtube/transcript.js:443

            || tracks.find(t => t.languageCode.startsWith(langPref));
        }
        if (!track) {
          track = tracks.find(t => t.kind !== 'asr') || tracks[0];
        }

        return {
          captionUrl: track.baseUrl,
          language: track.languageCode,
          kind: track.kind || 'manual',
          available,
          requestedLang: langPref || null,
          langMatched: !!(langPref && track.languageCode === langPref),
          langPrefixMatched: !!(langPref && track.languageCode !== langPref && track.languageCode.startsWith(langPref))
        };
      })()
    `));
        if (!segments && (!captionData || typeof captionData !== 'object' || Array.isArray(captionData))) {
            throw new CommandExecutionError(`Failed to get caption info: ${typeof captionData === 'string' ? captionData : 'malformed response'}`);
        }
        if (captionData?.error) {
            const msg = `${captionData.error}${captionData.available ? ' (available: ' + captionData.available.join(', ') + ')' : ''}`;
            // "No captions available" 是合法 empty 数据条件(作者没开字幕 + YT 没自动生成),
            // 与 bilibili subtitle 的 EmptyResultError 同模式。下游应按 code EMPTY_RESULT 跳过
            // 重试和 softFail 计数。其它 error(HTTP / parse / 短暂空响应)仍按 fetch 失败抛。
            if (captionData.error === 'No captions available for this video') {
                throw new EmptyResultError('youtube transcript', '该视频没有字幕(作者未开启 + 无自动字幕)。');
            }
            throw new CommandExecutionError(msg);
        }
        if (!segments && typeof captionData?.captionUrl !== 'string') {
            throw new CommandExecutionError('Malformed caption info payload');
        }
        // Warn if --lang was specified but not matched
        if (captionData?.requestedLang && !captionData.langMatched && !captionData.langPrefixMatched) {
            console.error(`Warning: --lang "${captionData.requestedLang}" not found. Using "${captionData.language}" instead. Available: ${captionData.available.join(', ')}`);
        }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. If the message contains an in-page error string, use it to identify the page-side failure.
  2. Wait for the player to be fully initialized before running extraction (add page-load readiness checks).
  3. Update the CLI so the injected caption-info script matches current YouTube player markup.
  4. Retry in a fresh session; consent/cookie walls often cause the script to return error strings.

Example fix

// before
const captionData = unwrapBrowserResult(await page.evaluate(`...`));
// after
const captionData = unwrapBrowserResult(await page.evaluate(`...`));
if (typeof captionData === 'string') {
  console.error('page script reported:', captionData);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const captionData = unwrapBrowserResult(await page.evaluate(`...`));
if (captionData == null || typeof captionData !== 'object' || Array.isArray(captionData)) {
  // handle malformed/string error response before proceeding
}

Type guard

function isCaptionInfo(v) {
  return !!v && typeof v === 'object' && !Array.isArray(v);
}

Try / catch

try {
  // caption info extraction
} catch (err) {
  if (err.message.startsWith('Failed to get caption info')) {
    console.error('page reported:', err.message); // string payloads carry the in-page error text
  }
}

Prevention

When it happens

Trigger: `segments` -> page.evaluate of the caption-info script returns a string (the script hit an error and returned a message) or null/undefined/array instead of the expected caption-info object.

Common situations: YouTube DOM changes breaking the captionTracks lookup script; videos with caption UI absent entirely; consent walls preventing player data; automated tab not fully loaded when evaluate runs.

Understand the failure class

Related errors


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