jackwener/OpenCLI · error · CommandExecutionError

${label}: unexpected evaluate result shape

Error message

${label}: unexpected evaluate result shape

What it means

CommandExecutionError thrown by requireArrayResult when the value unwrapped from page.evaluate() is not an array. The Qoder CLI expects injected browser scripts to resolve to arrays (items, turns) and fails loudly instead of iterating a non-array. The label names which result was malformed.

Source

Thrown at clis/qoder/_utils.js:40

    if (cs.visibility === 'hidden' || cs.display === 'none' || cs.opacity === '0') return false;
    return true;
  };
`;

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

export async function evaluateQoder(page, script) {
    return unwrapEvaluateResult(await page.evaluate(script));
}

export function requireArrayResult(value, label) {
    if (!Array.isArray(value)) {
        throw new CommandExecutionError(`${label}: unexpected evaluate result shape`);
    }
    return value;
}

export function parsePositiveInt(raw, fallback, label) {
    const value = raw == null || raw === '' ? fallback : Number(raw);
    if (!Number.isInteger(value) || value < 1) {
        throw new ArgumentError(`${label} must be a positive integer`);
    }
    return value;
}

// Build a JS snippet that clicks the first visible element matching any
// of the given CSS selectors. Uses the full pointer-event chain to
// satisfy radix/headless menu libraries.
export function clickFirstScript(selectors) {
    return `(() => {
    ${IS_VISIBLE_JS}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the raw evaluate result to inspect the actual shape
  2. Update the injected script to return an array (e.g. Array.from(nodeList))
  3. Check whether the target page structure changed and revise selectors
  4. Verify unwrapEvaluateResult handles your automation driver's result wrapper

Example fix

// before (in evaluate script)
return document.querySelectorAll('.item'); // NodeList, not array
// after
return Array.from(document.querySelectorAll('.item'));
Defensive patterns

Strategy: type-guard

Validate before calling

const result = await page.evaluate(script);
if (!Array.isArray(result)) console.error('evaluate returned:', result);

Type guard

function isArrayOf(v, pred = () => true) { return Array.isArray(v) && v.every(pred); }

Try / catch

let items;
try {
  items = requireArrayResult(await page.evaluate(script), 'items');
} catch (e) {
  if (/unexpected evaluate result shape/.test(e.message)) {
    // dump raw value, revise the injected script, or retry after navigation
  } else throw e;
}

Prevention

When it happens

Trigger: Calling a qoder command whose evaluate script returns undefined, null, an object, or a serialized wrapper instead of an array — e.g. the page's data source changed, the script was updated to return an object, or evaluate serialization dropped the value.

Common situations: Target web app updated its DOM/API so the injected script returns a different shape; the evaluated script hits an error path returning undefined; page context changed after navigation; browser automation layer returning wrapped results the unwrap step doesn't recognize.

Related errors


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