jackwener/OpenCLI · error · CommandExecutionError
String(payload.error)
Error message
String(payload.error)
What it means
normalizeSegmentsPayload validates the unwrapped result of a browser-evaluated YouTube player caption extraction. When the browser page returns an object with an `error` field (a structured in-page failure), the CLI rethrows it as a CommandExecutionError so the caller sees the real page-side reason instead of silent null segments. It is a deliberate error-propagation bridge from browser context to CLI context.
Source
Thrown at clis/youtube/transcript.js:31
import { extractJsonAssignmentFromHtml, parseVideoId, prepareYoutubeApiPage } from './utils.js';
import { groupTranscriptSegments, formatGroupedTranscript, } from './transcript-group.js';
import { CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
function unwrapBrowserResult(value) {
if (value && typeof value === 'object' && 'session' in value && 'data' in value) {
return value.data;
}
return value;
}
function normalizeSegmentsPayload(value, source, { allowNull = false } = {}) {
const payload = unwrapBrowserResult(value);
if (payload == null && allowNull)
return null;
if (Array.isArray(payload))
return payload;
if (payload && typeof payload === 'object' && payload.error) {
throw new CommandExecutionError(String(payload.error));
}
throw new CommandExecutionError(`Malformed ${source} payload`);
}
function parseJson3Segments(text) {
let data;
try {
data = JSON.parse(text);
}
catch (err) {
throw new CommandExecutionError(`Malformed json3 timedtext response: ${err?.message || err}`);
}
if (!Array.isArray(data?.events)) {
throw new CommandExecutionError('Malformed json3 timedtext response: missing events array');
}
const rows = [];
for (const event of data.events) {
const startMs = Number(event?.tStartMs || 0);View on GitHub (pinned to 49907e53dc)
Solutions
- Read the thrown message — it is the page-side error text — and fix the underlying in-page extraction cause (often a DOM/player API change).
- Update the YouTube CLI to the latest version so the injected player-extraction script matches current YouTube markup.
- Verify the browser tab/daemon session is fresh (restart the browser session) to clear stale SPA state.
- Check the video actually has captions; if not, handle the EMPTY_RESULT path instead of retrying.
Example fix
// before
const segments = normalizeSegmentsPayload(playerResult, 'player caption extraction', { allowNull: true });
// after
try {
const segments = normalizeSegmentsPayload(playerResult, 'player caption extraction', { allowNull: true });
} catch (err) {
console.error('player caption extraction failed:', err.message);
// fall back to network-capture path
} Defensive patterns
Strategy: try-catch
Validate before calling
if (payload && typeof payload === 'object' && !Array.isArray(payload) && payload.error) {
// page reported an error; handle before calling the extractor
} Type guard
function isSegmentsPayload(v) {
return v == null || Array.isArray(v) || (typeof v === 'object' && !('error' in v));
} Try / catch
try {
const segments = normalizeSegmentsPayload(playerResult, 'player caption extraction', { allowNull: true });
} catch (err) {
// err.message is the page-side error text; log and fall back to network capture
} Prevention
- Always unwrap and shape-check browser results before consuming them
- Keep the CLI updated against YouTube player API changes
- Use fresh browser sessions for shared daemon tabs
- Confirm the video has captions before extraction
When it happens
Trigger: Calling `segments` -> `normalizeSegmentsPayload(playerResult, ...)` where the in-page evaluate returned {error: "..."} — e.g. the YouTube player response lacked captionTracks or the page script caught its own failure and serialized it as an error field.
Common situations: YouTube DOM/player changes breaking the injected caption-extraction script; videos where caption data is gated (age-restricted, consent walls); stale browser tab in a shared daemon session returning a cached error object.
Related errors
- Codex extract-diff returned an invalid payload.
- LinkedIn sent invitations returned a malformed extraction pa
- Manus credits returned a malformed API payload
- Weibo whoami returned malformed probe payload
- Xianyu ${label} returned malformed browser payload
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/762b2fab6d57b95d.
Report an issue: GitHub.