jackwener/OpenCLI · error · CommandExecutionError

Failed to extract video metadata from page

Error message

Failed to extract video metadata from page

What it means

CommandExecutionError thrown by requireVideoPayload when the browser result, after unwrapBrowserResult, is not a usable object (null, non-object, or array). The library uses this to signal that the page-side video metadata extraction returned nothing usable, rather than returning partial or invalid data to the caller.

Source

Thrown at clis/youtube/video.js:18

/**
 * YouTube video metadata — fetch watch HTML and parse bootstrap data without opening the watch UI.
 */
import { cli, Strategy } from '@jackwener/opencli/registry';
import { extractJsonAssignmentFromHtml, parseVideoId, prepareYoutubeApiPage } from './utils.js';
import { CommandExecutionError } from '@jackwener/opencli/errors';

function unwrapBrowserResult(value) {
    if (value && typeof value === 'object' && 'session' in value && 'data' in value) {
        return value.data;
    }
    return value;
}

function requireVideoPayload(value) {
    const payload = unwrapBrowserResult(value);
    if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
        throw new CommandExecutionError('Failed to extract video metadata from page');
    }
    if (payload.error) {
        throw new CommandExecutionError(String(payload.error));
    }
    if (typeof payload.playabilityStatus !== 'string') {
        throw new CommandExecutionError('YouTube video metadata is missing playabilityStatus');
    }
    if (typeof payload.playabilityReason !== 'string') {
        throw new CommandExecutionError('YouTube video metadata is missing playabilityReason');
    }
    if (typeof payload.membersOnly !== 'boolean') {
        throw new CommandExecutionError('YouTube video metadata is missing membersOnly');
    }
    return payload;
}

cli({
    site: 'youtube',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the raw browser result before calling the command to see what the page evaluation actually returned.
  2. Ensure the video page loaded fully before extraction (use prepareYoutubeApiPage / wait for ytcfg and player data).
  3. Retry the extraction — transient navigation/serialization failures often succeed on a second attempt.
  4. Check the target URL parses to a valid videoId; invalid URLs can lead the page script to return null metadata.
  5. Update the library if YouTube changed page structure, breaking the extraction script.
Defensive patterns

Strategy: type-guard

Validate before calling

const raw = await getPageVideoPayload(page);
if (raw == null || typeof raw !== 'object' || Array.isArray(raw)) {
  throw new Error('Extraction returned no usable payload');
}

Type guard

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

Try / catch

try {
  const info = await video(url);
} catch (e) {
  if (e.name === 'CommandExecutionError' && /extract video metadata/.test(e.message)) {
    return retryExtraction(url, 1);
  }
  throw e;
}

Prevention

When it happens

Trigger: page.evaluate for video metadata resolved to null/undefined/a primitive/an array — e.g. the extraction script crashed in a way that returned null, or the browser result wrapper unwrapped to an unexpected type.

Common situations: Navigation or serialization failure inside the page so evaluate resolved null; extraction run before the watch page loaded; a malformed URL leading the in-page script to bail out; YouTube page changes breaking the extraction script entirely.

Related errors


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