jackwener/OpenCLI · error · CommandExecutionError

${label} returned an unexpected payload shape; expected an o

Error message

${label} returned an unexpected payload shape; expected an object.

What it means

A CommandExecutionError thrown by assertPlainObject (clis/dongchedi/utils.js:110), a schema guard used by the head/ov parsers. It fires when a pageProps field that the parser expects to be a plain JSON object is instead null, an array, a string, or another non-object type. It protects downstream property accesses from crashing on unexpected payload shapes after upstream layout changes.

Source

Thrown at clis/dongchedi/utils.js:110

    const pp = extractPageProps(html);
    if (!pp) {
        throw new CommandExecutionError(
            `dongchedi ${contextHint} returned no __NEXT_DATA__`,
            'Dongchedi likely changed its page structure, or the request hit an anti-bot page.',
        );
    }
    if (isFallbackShell(pp)) {
        throw new CommandExecutionError(
            `dongchedi ${contextHint}`,
            'Dongchedi served its empty fallback shell — the id may not exist or the URL form changed.',
        );
    }
    return pp;
}

export function assertPlainObject(value, label) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        throw new CommandExecutionError(`${label} returned an unexpected payload shape; expected an object.`);
    }
    return value;
}

export function requireArray(value, label) {
    if (!Array.isArray(value)) {
        throw new CommandExecutionError(`${label} returned an unexpected payload shape; expected an array.`);
    }
    return value;
}

export function requireStableId(value, label) {
    const id = String(value ?? '').trim();
    if (!/^\d+$/.test(id) || id === '0') {
        throw new CommandExecutionError(`${label} did not include a stable numeric id.`);
    }
    return id;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the live pageProps to see the actual type of the labeled field and update the parser to match.
  2. If the data legitimately doesn't exist for this item, treat it as empty output rather than forcing the parse.
  3. Catch CommandExecutionError in the command wrapper and report which labeled block was malformed.
  4. When building test fixtures, ensure the mocked field matches the real SSR shape (a plain object).

Example fix

// before
const head = assertPlainObject(pp.someBlock, 'head'); // throws if null
// after
const head = pp.someBlock && !Array.isArray(pp.someBlock)
  ? assertPlainObject(pp.someBlock, 'head')
  : defaultEmptyHead;
Defensive patterns

Strategy: type-guard

Type guard

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

Try / catch

if (!isPlainObject(pp.expectedBlock)) {
  return emptyResult('expected block missing'); // pre-validate before the parser throws
}
const head = assertPlainObject(pp.expectedBlock, 'head');

Prevention

When it happens

Trigger: Calling a dongchedi command whose parser invokes assertPlainObject (e.g. head/ov data blocks) when the site returns null for that block (missing data, soft-deleted content), wraps it in an array, or changed its type in a layout update.

Common situations: Scraping series or reviews whose overview block is absent; Dongchedi shipping a schema change (object → array) in a redeploy; fixtures/tests feeding hand-built payloads of the wrong shape.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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