jackwener/OpenCLI · error · CommandExecutionError

Unexpected SMZDM search extraction payload shape; expected a

Error message

Unexpected SMZDM search extraction payload shape; expected an array of rows.

What it means

requireSearchRows validates that the payload returned from the SMZDM in-page extraction script is an array of result rows after unwrapping an evaluate() result. If the browser-side script returns an object, null, or an error-shaped value instead of an array, the payload shape is considered broken and the CLI refuses to continue rather than crash downstream with a confusing TypeError. This is a defensive contract check on automation output.

Source

Thrown at clis/smzdm/search.js:21

 *
 * Fix: The old adapter used `search.smzdm.com/ajax/` which returns 404.
 * New approach: navigate to `search.smzdm.com/?c=home&s=<keyword>&v=b`
 * and scrape the rendered DOM directly.
 */
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';

function unwrapEvaluateResult(payload) {
    if (payload && !Array.isArray(payload) && typeof payload === 'object' && 'session' in payload && 'data' in payload) {
        return payload.data;
    }
    return payload;
}

function requireSearchRows(payload) {
    const rows = unwrapEvaluateResult(payload);
    if (!Array.isArray(rows)) {
        throw new CommandExecutionError('Unexpected SMZDM search extraction payload shape; expected an array of rows.');
    }
    return rows;
}

function parseLimit(raw) {
    let parsed;
    if (raw == null) {
        parsed = 20;
    }
    else if (typeof raw === 'number') {
        parsed = raw;
    }
    else if (typeof raw === 'string' && /^[0-9]+$/.test(raw)) {
        parsed = Number(raw);
    }
    else {
        parsed = NaN;
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command to rule out a transient anti-bot or rate-limit page interception.
  2. Inspect the raw payload (log unwrapEvaluateResult(payload)) to see what shape actually came back.
  3. Update the SMZDM extraction script selectors to match the current search page markup.
  4. Check the automation/browser driver version for evaluate() result-serialization changes.

Example fix

// before: assume array, crash with TypeError on .map
const rows = unwrapEvaluateResult(payload);
return rows.map(formatRow);
// after: validate first (what requireSearchRows does)
const rows = unwrapEvaluateResult(payload);
if (!Array.isArray(rows)) throw new CommandExecutionError('Unexpected SMZDM search extraction payload shape; expected an array of rows.');
Defensive patterns

Strategy: type-guard

Type guard

function isRows(payload) { return Array.isArray(unwrapEvaluateResult(payload)); }
if (!isRows(payload)) { /* bail out or log payload before calling the command */ }

Try / catch

try {
  const rows = requireSearchRows(payload);
} catch (e) {
  console.error('SMZDM extraction returned non-array; raw payload:', JSON.stringify(unwrapEvaluateResult(payload)));
  // fall back to retry or surface a user-facing 'site layout may have changed' message
}

Prevention

When it happens

Trigger: smzdmSearchCommand runs the extraction script via unwrapEvaluateResult(payload) and the result is not an Array — e.g. the page DOM changed so the script returns an error object, the browser evaluate call failed and returned {error: ...} or null, or a rate-limit/anti-bot page was served instead of results.

Common situations: SMZDM changes its search page markup so the injected selector-based script returns {} or an error payload; anti-bot interception returns a challenge page; the automation driver wraps results differently after a driver upgrade; the site returns a login wall so the script bails with a non-array value.

Related errors


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