jackwener/OpenCLI · error · CommandExecutionError

${label} returned malformed extraction payload

Error message

${label} returned malformed extraction payload

What it means

The fallback branch of requireArrayEvaluateResult: when a page.evaluate payload is not an array AND does not carry an {error} envelope, a CommandExecutionError with '<label> returned malformed extraction payload' is thrown. It signals the injected script's contract was violated by the page context.

Source

Thrown at clis/chatgpt/utils.js:209

// weibo (#1568).
//
// `unwrapEvaluateResult` is a defensive ternary: it unwraps when the payload
// looks like an envelope, otherwise passes the value through unchanged so
// older bridge versions and primitive return values still work.
// ─────────────────────────────────────────────────────────────────────────────
export function unwrapEvaluateResult(payload) {
    if (payload && !Array.isArray(payload) && typeof payload === 'object' && 'session' in payload && 'data' in payload) {
        return payload.data;
    }
    return payload;
}

export function requireArrayEvaluateResult(payload, label) {
    if (!Array.isArray(payload)) {
        if (payload && typeof payload === 'object' && 'error' in payload) {
            throw new CommandExecutionError(`${label}: ${String(payload.error)}`);
        }
        throw new CommandExecutionError(`${label} returned malformed extraction payload`);
    }
    return payload;
}

export function requireObjectEvaluateResult(payload, label) {
    if (!payload || Array.isArray(payload) || typeof payload !== 'object') {
        throw new CommandExecutionError(`${label} returned malformed extraction payload`);
    }
    return payload;
}

export function requireBooleanEvaluateResult(payload, label) {
    if (typeof payload !== 'boolean') {
        throw new CommandExecutionError(`${label} returned malformed extraction payload`);
    }
    return payload;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Ensure the browser is on a fully loaded chatgpt.com page before running extraction commands
  2. Retry — transient navigation/render races commonly return undefined
  3. Log the actual payload (enable debug output) to see what shape came back
  4. Update opencli if ChatGPT's markup changed

Example fix

// before
const urls = await getChatGPTImageAssets(page); // page still loading -> undefined
// after
await page.waitForFunction(() => document.querySelectorAll('img').length > 0);
const urls = await getChatGPTImageAssets(page);
Defensive patterns

Strategy: retry

Type guard

function isArrayEvaluatePayload(p) { return Array.isArray(p); }

Try / catch

try { items = await getChatGPTImageAssets(page); } catch (e) { if (e instanceof CommandExecutionError && e.message.includes('malformed')) { await page.waitForTimeout(2000); items = await getChatGPTImageAssets(page); } else throw e; }

Prevention

When it happens

Trigger: page.evaluate returns null/undefined (script returned nothing), a scalar, or an object without an 'error' key where an array of items was expected.

Common situations: Navigating mid-extraction so the evaluate context is destroyed or returns undefined, ChatGPT DOM changes, or running against a non-chatgpt page/blank tab.

Understand the failure class

Related errors


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